/// Check whether a function's parameter types are all literal types. If so,
/// return true. If not, produce a suitable diagnostic and return false.
-/// If any ParamDecl is null, return false without producing a diagnostic.
-/// The code creating null parameters is responsible for producing a diagnostic.
static bool CheckConstexprParameterTypes(Sema &SemaRef,
const FunctionDecl *FD,
Sema::CheckConstexprKind Kind) {
e = FT->param_type_end();
i != e; ++i, ++ArgIndex) {
const ParmVarDecl *PD = FD->getParamDecl(ArgIndex);
- if (!PD)
- return false;
+ assert(PD && "null in a parameter list");
SourceLocation ParamLoc = PD->getLocation();
if (CheckLiteralType(SemaRef, Kind, ParamLoc, *i,
diag::err_constexpr_non_literal_param, ArgIndex + 1,
// Walk the DeclTypeInfo, building the recursive type as we go.
// DeclTypeInfos are ordered from the identifier out, which is
// opposite of what we want :).
+
+ // Track if the produced type matches the structure of the declarator.
+ // This is used later to decide if we can fill `TypeLoc` from
+ // `DeclaratorChunk`s. E.g. it must be false if Clang recovers from
+ // an error by replacing the type with `int`.
+ bool AreDeclaratorChunksValid = true;
for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
unsigned chunkIndex = e - i - 1;
state.setCurrentChunkIndex(chunkIndex);
: diag::err_deduced_return_type);
T = Context.IntTy;
D.setInvalidType(true);
+ AreDeclaratorChunksValid = false;
} else {
S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
diag::warn_cxx11_compat_deduced_return_type);
S.Diag(D.getBeginLoc(), diag::err_trailing_return_in_parens)
<< T << D.getSourceRange();
D.setInvalidType(true);
+ // FIXME: recover and fill decls in `TypeLoc`s.
+ AreDeclaratorChunksValid = false;
} else if (D.getName().getKind() ==
UnqualifiedIdKind::IK_DeductionGuideName) {
if (T != Context.DependentTy) {
diag::err_deduction_guide_with_complex_decl)
<< D.getSourceRange();
D.setInvalidType(true);
+ // FIXME: recover and fill decls in `TypeLoc`s.
+ AreDeclaratorChunksValid = false;
}
} else if (D.getContext() != DeclaratorContext::LambdaExpr &&
(T.hasQualifiers() || !isa<AutoType>(T) ||
diag::err_trailing_return_without_auto)
<< T << D.getDeclSpec().getSourceRange();
D.setInvalidType(true);
+ // FIXME: recover and fill decls in `TypeLoc`s.
+ AreDeclaratorChunksValid = false;
}
T = S.GetTypeFromParser(FTI.getTrailingReturnType(), &TInfo);
if (T.isNull()) {
S.Diag(DeclType.Loc, diagID) << T->isFunctionType() << T;
T = Context.IntTy;
D.setInvalidType(true);
+ AreDeclaratorChunksValid = false;
}
// Do not allow returning half FP value.
ObjCObjectPointerTypeLoc TLoc = TLB.push<ObjCObjectPointerTypeLoc>(T);
TLoc.setStarLoc(FixitLoc);
TInfo = TLB.getTypeSourceInfo(Context, T);
+ } else {
+ AreDeclaratorChunksValid = false;
}
D.setInvalidType(true);
T = (!LangOpts.requiresStrictPrototypes() && !LangOpts.OpenCL)
? Context.getFunctionNoProtoType(T, EI)
: Context.IntTy;
+ AreDeclaratorChunksValid = false;
break;
}
if (!ClsType.isNull())
T = S.BuildMemberPointerType(T, ClsType, DeclType.Loc,
D.getIdentifier());
+ else
+ AreDeclaratorChunksValid = false;
+
if (T.isNull()) {
T = Context.IntTy;
D.setInvalidType(true);
+ AreDeclaratorChunksValid = false;
} else if (DeclType.Mem.TypeQuals) {
T = S.BuildQualifiedType(T, DeclType.Loc, DeclType.Mem.TypeQuals);
}
if (T.isNull()) {
D.setInvalidType(true);
T = Context.IntTy;
+ AreDeclaratorChunksValid = false;
}
// See if there are any attributes on this declarator chunk.
}
assert(!T.isNull() && "T must not be null at the end of this function");
- if (D.isInvalidType())
+ if (!AreDeclaratorChunksValid)
return Context.getTrivialTypeSourceInfo(T);
-
return GetTypeSourceInfoForDeclarator(state, T, TInfo);
}