diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -15884,10 +15884,7 @@ bool CheckParameterNames) { bool HasInvalidParm = false; for (ParmVarDecl *Param : Parameters) { - if (!Param) { - HasInvalidParm = true; - continue; - } + assert(Param && "null in a parameter list"); // C99 6.7.5.3p4: the parameters in a parameter type list in a // function declarator that is part of a function definition of // that function shall not have incomplete type. diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -1712,8 +1712,6 @@ /// 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) { @@ -1723,8 +1721,7 @@ 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, diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -956,8 +956,7 @@ CheckParmsForFunctionDef(Params, /*CheckParameterNames=*/false); Method->setParams(Params); for (auto P : Method->parameters()) { - if (!P) - continue; + assert(P && "null in a parameter list"); P->setOwningFunction(Method); } } diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -1355,7 +1355,8 @@ CXXMethodDecl *MD = Result.getAs()->getCallOperator(); for (ParmVarDecl *PVD : MD->parameters()) { - if (!PVD || !PVD->hasDefaultArg()) + assert(PVD && "null in a parameter list"); + if (!PVD->hasDefaultArg()) continue; Expr *UninstExpr = PVD->getUninstantiatedDefaultArg(); // FIXME: Obtain the source location for the '=' token. diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -4979,6 +4979,12 @@ // 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); @@ -5172,6 +5178,7 @@ : 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); @@ -5182,6 +5189,8 @@ 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) { @@ -5189,6 +5198,8 @@ 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(T) || @@ -5199,6 +5210,8 @@ 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()) { @@ -5239,6 +5252,7 @@ S.Diag(DeclType.Loc, diagID) << T->isFunctionType() << T; T = Context.IntTy; D.setInvalidType(true); + AreDeclaratorChunksValid = false; } // Do not allow returning half FP value. @@ -5305,6 +5319,8 @@ ObjCObjectPointerTypeLoc TLoc = TLB.push(T); TLoc.setStarLoc(FixitLoc); TInfo = TLB.getTypeSourceInfo(Context, T); + } else { + AreDeclaratorChunksValid = false; } D.setInvalidType(true); @@ -5425,6 +5441,7 @@ T = (!LangOpts.requiresStrictPrototypes() && !LangOpts.OpenCL) ? Context.getFunctionNoProtoType(T, EI) : Context.IntTy; + AreDeclaratorChunksValid = false; break; } @@ -5659,9 +5676,13 @@ 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); } @@ -5679,6 +5700,7 @@ if (T.isNull()) { D.setInvalidType(true); T = Context.IntTy; + AreDeclaratorChunksValid = false; } // See if there are any attributes on this declarator chunk. @@ -5937,9 +5959,8 @@ } 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); } diff --git a/clang/test/Index/complete-blocks.m b/clang/test/Index/complete-blocks.m --- a/clang/test/Index/complete-blocks.m +++ b/clang/test/Index/complete-blocks.m @@ -85,4 +85,4 @@ // CHECK-CC8: ObjCInstanceMethodDecl:{ResultType id}{TypedText method7:}{Placeholder ^int(int x, int y)b} (35) // RUN: c-index-test -code-completion-at=%s:59:6 %s | FileCheck -check-prefix=CHECK-CC9 %s -// CHECK-CC9: ObjCInstanceMethodDecl:{ResultType void}{TypedText foo:}{Placeholder ^int *(int)arg} (35) +// CHECK-CC9: ObjCInstanceMethodDecl:{ResultType void}{TypedText foo:}{Placeholder ^int *(float)arg} (35)