diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index d6a0a88960d6..3d8377e95826 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -390,6 +390,7 @@ Miscellaneous Clang Crashes Fixed - Fixed a crash when using loop hint with a value dependent argument inside a generic lambda. (#GH172289) - Fixed a crash in C++ overload resolution with ``_Atomic``-qualified argument types. (#GH170433) +- Fixed a crash related to missing source locations (#GH186655) - Fixed a crash when casting a parenthesized unresolved template-id or array section. (#GH183505) - Fixed a crash when initializing a ``constexpr`` pointer with a floating-point literal in C23. (#GH180313) - Fixed an assertion when diagnosing address-space qualified ``new``/``delete`` in language-defined address spaces such as OpenCL ``__local``. (#GH178319) diff --git a/clang/include/clang/AST/TemplateBase.h b/clang/include/clang/AST/TemplateBase.h index de248ac3cf70..c0db55ea92cd 100644 --- a/clang/include/clang/AST/TemplateBase.h +++ b/clang/include/clang/AST/TemplateBase.h @@ -493,6 +493,10 @@ struct TemplateArgumentLocInfo { TemplateArgumentLocInfo(TypeSourceInfo *Declarator) { Pointer = Declarator; } TemplateArgumentLocInfo(Expr *E) { Pointer = E; } + + // For trivial source locations for converted template argument kinds. + TemplateArgumentLocInfo(ASTContext &Ctx, SourceLocation Loc); + // Ctx is used for allocation -- this case is unusually large and also rare, // so we store the payload out-of-line. TemplateArgumentLocInfo(ASTContext &Ctx, SourceLocation TemplateKwLoc, @@ -518,9 +522,28 @@ struct TemplateArgumentLocInfo { return getTemplate()->EllipsisLoc; } + bool isNull() const { return Pointer.isNull(); } + + bool isTrivial() const { return isa(Pointer); } + + SourceLocation getTrivialLoc() const { + auto *P = cast(Pointer); + if constexpr (EmbedLocInPointer) + return SourceLocation::getFromRawEncoding( + (reinterpret_cast(P) >> LowBitsRequired) - 1u); + else + return *static_cast(P); + } + private: - llvm::PointerUnion + static constexpr bool EmbedLocInPointer = sizeof(void *) > + sizeof(SourceLocation); + using LocOrPointer = + std::conditional_t *; + llvm::PointerUnion Pointer; + static constexpr unsigned LowBitsRequired = 2; }; /// Location wrapper for a TemplateArgument. TemplateArgument is to @@ -534,16 +557,43 @@ public: TemplateArgumentLoc(const TemplateArgument &Argument, TemplateArgumentLocInfo Opaque) - : Argument(Argument), LocInfo(Opaque) {} + : Argument(Argument), LocInfo(Opaque) { + switch (Argument.getKind()) { + case TemplateArgument::Null: + assert(Opaque.isNull()); + return; + case TemplateArgument::Pack: + assert(Opaque.isTrivial()); + return; + case TemplateArgument::NullPtr: + case TemplateArgument::Integral: + case TemplateArgument::Declaration: + case TemplateArgument::StructuralValue: + assert(Opaque.isTrivial() || Opaque.getAsExpr() != nullptr); + return; + case TemplateArgument::Expression: + assert(Opaque.getAsExpr() != nullptr); + return; + case TemplateArgument::Type: + assert(Opaque.getAsTypeSourceInfo() != nullptr); + return; + case TemplateArgument::Template: + case TemplateArgument::TemplateExpansion: + assert(Opaque.getTemplate() != nullptr); + return; + } + llvm_unreachable("Unknown TemplateArgument kind"); + } TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo) : Argument(Argument), LocInfo(TInfo) { assert(Argument.getKind() == TemplateArgument::Type); + assert(TInfo != nullptr); } TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E) : Argument(Argument), LocInfo(E) { - + assert(E != nullptr); // Permit any kind of template argument that can be represented with an // expression. assert(Argument.getKind() == TemplateArgument::NullPtr || diff --git a/clang/lib/AST/TemplateBase.cpp b/clang/lib/AST/TemplateBase.cpp index 131ae6e8a478..ee5bb80fc36e 100644 --- a/clang/lib/AST/TemplateBase.cpp +++ b/clang/lib/AST/TemplateBase.cpp @@ -626,9 +626,13 @@ SourceRange TemplateArgumentLoc::getSourceRange() const { return getSourceExpression()->getSourceRange(); case TemplateArgument::Declaration: + if (LocInfo.isTrivial()) + return SourceRange(LocInfo.getTrivialLoc()); return getSourceDeclExpression()->getSourceRange(); case TemplateArgument::NullPtr: + if (LocInfo.isTrivial()) + return SourceRange(LocInfo.getTrivialLoc()); return getSourceNullPtrExpression()->getSourceRange(); case TemplateArgument::Type: @@ -650,12 +654,18 @@ SourceRange TemplateArgumentLoc::getSourceRange() const { return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc()); case TemplateArgument::Integral: + if (LocInfo.isTrivial()) + return SourceRange(LocInfo.getTrivialLoc()); return getSourceIntegralExpression()->getSourceRange(); case TemplateArgument::StructuralValue: + if (LocInfo.isTrivial()) + return SourceRange(LocInfo.getTrivialLoc()); return getSourceStructuralValueExpression()->getSourceRange(); case TemplateArgument::Pack: + return SourceRange(LocInfo.getTrivialLoc()); + case TemplateArgument::Null: return SourceRange(); } @@ -737,6 +747,15 @@ clang::TemplateArgumentLocInfo::TemplateArgumentLocInfo( Pointer = Template; } +clang::TemplateArgumentLocInfo::TemplateArgumentLocInfo( + ASTContext &Ctx, SourceLocation TrivialLoc) { + if constexpr (EmbedLocInPointer) + Pointer = reinterpret_cast((TrivialLoc.getRawEncoding() + 1u) + << LowBitsRequired); + else + Pointer = new (Ctx) SourceLocation(TrivialLoc); +} + const ASTTemplateArgumentListInfo * ASTTemplateArgumentListInfo::Create(const ASTContext &C, const TemplateArgumentListInfo &List) { diff --git a/clang/lib/AST/TypeLoc.cpp b/clang/lib/AST/TypeLoc.cpp index 53edfdb65a4d..7e72a8513696 100644 --- a/clang/lib/AST/TypeLoc.cpp +++ b/clang/lib/AST/TypeLoc.cpp @@ -723,11 +723,12 @@ void TemplateSpecializationTypeLoc::initializeArgLocs( case TemplateArgument::Null: llvm_unreachable("Impossible TemplateArgument"); + case TemplateArgument::Pack: case TemplateArgument::Integral: case TemplateArgument::Declaration: case TemplateArgument::NullPtr: case TemplateArgument::StructuralValue: - ArgInfos[i] = TemplateArgumentLocInfo(); + ArgInfos[i] = TemplateArgumentLocInfo(Context, Loc); break; case TemplateArgument::Expression: @@ -755,10 +756,6 @@ void TemplateSpecializationTypeLoc::initializeArgLocs( : Loc); break; } - - case TemplateArgument::Pack: - ArgInfos[i] = TemplateArgumentLocInfo(); - break; } } } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index db6d93ce5479..2b0a786302aa 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2366,14 +2366,14 @@ Sema::ActOnStringLiteral(ArrayRef StringToks, Scope *UDLScope) { TemplateArgumentLocInfo TypeArgInfo(Context.getTrivialTypeSourceInfo(CharTy)); ExplicitArgs.addArgument(TemplateArgumentLoc(TypeArg, TypeArgInfo)); + SourceLocation Loc = StringTokLocs.back(); for (unsigned I = 0, N = Lit->getLength(); I != N; ++I) { Value = Lit->getCodeUnit(I); TemplateArgument Arg(Context, Value, CharTy); - TemplateArgumentLocInfo ArgInfo; + TemplateArgumentLocInfo ArgInfo(Context, Loc.getLocWithOffset(I)); ExplicitArgs.addArgument(TemplateArgumentLoc(Arg, ArgInfo)); } - return BuildLiteralOperatorCall(R, OpNameInfo, {}, StringTokLocs.back(), - &ExplicitArgs); + return BuildLiteralOperatorCall(R, OpNameInfo, {}, Loc, &ExplicitArgs); } case LOLR_Raw: case LOLR_ErrorNoDiagnostic: @@ -3915,7 +3915,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { for (unsigned I = 0, N = Literal.getUDSuffixOffset(); I != N; ++I) { Value = TokSpelling[I]; TemplateArgument Arg(Context, Value, Context.CharTy); - TemplateArgumentLocInfo ArgInfo; + TemplateArgumentLocInfo ArgInfo(Context, TokLoc.getLocWithOffset(I)); ExplicitArgs.addArgument(TemplateArgumentLoc(Arg, ArgInfo)); } return BuildLiteralOperatorCall(R, OpNameInfo, {}, TokLoc, &ExplicitArgs); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index c3ff9f83be36..5d23660585ea 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -5972,9 +5972,9 @@ bool Sema::CheckTemplateArgumentList( CTAI.CanonicalConverted, Params->getDepth())); } - ArgLoc = - TemplateArgumentLoc(TemplateArgument::CreatePackCopy(Context, Args), - ArgLoc.getLocInfo()); + ArgLoc = TemplateArgumentLoc( + TemplateArgument::CreatePackCopy(Context, Args), + TemplateArgumentLocInfo(Context, ArgLoc.getLocation())); } else { SaveAndRestore _1(CTAI.PartialOrdering, false); if (CheckTemplateArgument(*Param, ArgLoc, Template, TemplateLoc, diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 265e5f4d2491..f18a34415ba4 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -2908,7 +2908,7 @@ Sema::getTrivialTemplateArgumentLoc(const TemplateArgument &Arg, return TemplateArgumentLoc(Arg, Arg.getAsExpr()); case TemplateArgument::Pack: - return TemplateArgumentLoc(Arg, TemplateArgumentLocInfo()); + return TemplateArgumentLoc(Arg, TemplateArgumentLocInfo(Context, Loc)); } llvm_unreachable("Invalid TemplateArgument Kind!"); diff --git a/clang/test/SemaCXX/type_pack_element.cpp b/clang/test/SemaCXX/type_pack_element.cpp index d22d5fa2ba67..0509358887af 100644 --- a/clang/test/SemaCXX/type_pack_element.cpp +++ b/clang/test/SemaCXX/type_pack_element.cpp @@ -43,3 +43,10 @@ static_assert(__is_same(__type_pack_element<5, X<0>, X<1>, X<2>, X<3>, X<4>, X<5 template using ErrorTypePackElement1 = __type_pack_element; // expected-error{{may not be accessed at an out of bounds index}} using illformed1 = ErrorTypePackElement1<3, X<0>, X<1>>; // expected-note{{in instantiation}} + +namespace GH186655 { + template struct S; + // expected-error@-1 {{cannot be defined in a type specifier}} + template struct S> {}; + // expected-error@-1 {{a parameter pack may not be accessed at an out of bounds index}} +} // namespace GH186655