diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -960,6 +960,11 @@ T->getStmtClass() <= lastExprConstant; } }; +// PointerLikeTypeTraits is specialized so it can be used with a forward-decl of +// Expr. Verify that we got it right. +static_assert(llvm::PointerLikeTypeTraits::NumLowBitsAvailable <= + llvm::detail::ConstantLog2::value, + "PointerLikeTypeTraits assumes too much alignment."); //===----------------------------------------------------------------------===// // Wrapper Expressions. diff --git a/clang/include/clang/AST/TemplateBase.h b/clang/include/clang/AST/TemplateBase.h --- a/clang/include/clang/AST/TemplateBase.h +++ b/clang/include/clang/AST/TemplateBase.h @@ -36,6 +36,17 @@ class FoldingSetNodeID; +// Provide PointerLikeTypeTraits for clang::Expr*, this default one requires a +// full definition of Expr, but this file only sees a forward del because of +// the dependency. +template <> struct PointerLikeTypeTraits { + static inline void *getAsVoidPointer(clang::Expr *P) { return P; } + static inline clang::Expr *getFromVoidPointer(void *P) { + return static_cast(P); + } + static constexpr int NumLowBitsAvailable = 2; +}; + } // namespace llvm namespace clang { @@ -393,7 +404,7 @@ /// Location information for a TemplateArgument. struct TemplateArgumentLocInfo { private: - struct T { + struct TemplateTemplateArgLocInfo { // FIXME: We'd like to just use the qualifier in the TemplateName, // but template arguments get canonicalized too quickly. NestedNameSpecifier *Qualifier; @@ -402,47 +413,42 @@ unsigned EllipsisLoc; }; - union { - struct T Template; - Expr *Expression; - TypeSourceInfo *Declarator; - }; - -public: - constexpr TemplateArgumentLocInfo() : Template({nullptr, nullptr, 0, 0}) {} + llvm::PointerUnion + Pointer; - TemplateArgumentLocInfo(TypeSourceInfo *TInfo) : Declarator(TInfo) {} + TemplateTemplateArgLocInfo *getTemplate() const { + return Pointer.get(); + } - TemplateArgumentLocInfo(Expr *E) : Expression(E) {} +public: + constexpr TemplateArgumentLocInfo() {} + TemplateArgumentLocInfo(TypeSourceInfo *Declarator) { Pointer = Declarator; } - TemplateArgumentLocInfo(NestedNameSpecifierLoc QualifierLoc, + TemplateArgumentLocInfo(Expr *E) { Pointer = E; } + // Ctx is used for allocation -- this case is unusually large and also rare, + // so we store the payload out-of-line. + TemplateArgumentLocInfo(ASTContext &Ctx, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateNameLoc, - SourceLocation EllipsisLoc) { - Template.Qualifier = QualifierLoc.getNestedNameSpecifier(); - Template.QualifierLocData = QualifierLoc.getOpaqueData(); - Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding(); - Template.EllipsisLoc = EllipsisLoc.getRawEncoding(); - } + SourceLocation EllipsisLoc); TypeSourceInfo *getAsTypeSourceInfo() const { - return Declarator; + return Pointer.get(); } - Expr *getAsExpr() const { - return Expression; - } + Expr *getAsExpr() const { return Pointer.get(); } NestedNameSpecifierLoc getTemplateQualifierLoc() const { - return NestedNameSpecifierLoc(Template.Qualifier, - Template.QualifierLocData); + const auto *Template = getTemplate(); + return NestedNameSpecifierLoc(Template->Qualifier, + Template->QualifierLocData); } SourceLocation getTemplateNameLoc() const { - return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc); + return SourceLocation::getFromRawEncoding(getTemplate()->TemplateNameLoc); } SourceLocation getTemplateEllipsisLoc() const { - return SourceLocation::getFromRawEncoding(Template.EllipsisLoc); + return SourceLocation::getFromRawEncoding(getTemplate()->EllipsisLoc); } }; @@ -475,12 +481,12 @@ Argument.getKind() == TemplateArgument::Expression); } - TemplateArgumentLoc(const TemplateArgument &Argument, + TemplateArgumentLoc(ASTContext &Ctx, const TemplateArgument &Argument, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateNameLoc, SourceLocation EllipsisLoc = SourceLocation()) : Argument(Argument), - LocInfo(QualifierLoc, TemplateNameLoc, EllipsisLoc) { + LocInfo(Ctx, QualifierLoc, TemplateNameLoc, EllipsisLoc) { assert(Argument.getKind() == TemplateArgument::Template || Argument.getKind() == TemplateArgument::TemplateExpansion); } diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -882,11 +882,9 @@ import(FromInfo.getTemplateEllipsisLoc()); if (!ToTemplateEllipsisLocOrErr) return ToTemplateEllipsisLocOrErr.takeError(); - ToInfo = TemplateArgumentLocInfo( - *ToTemplateQualifierLocOrErr, - *ToTemplateNameLocOrErr, - *ToTemplateEllipsisLocOrErr); + Importer.getToContext(), *ToTemplateQualifierLocOrErr, + *ToTemplateNameLocOrErr, *ToTemplateEllipsisLocOrErr); } return TemplateArgumentLoc(Arg, ToInfo); diff --git a/clang/lib/AST/TemplateBase.cpp b/clang/lib/AST/TemplateBase.cpp --- a/clang/lib/AST/TemplateBase.cpp +++ b/clang/lib/AST/TemplateBase.cpp @@ -502,6 +502,17 @@ llvm_unreachable("Invalid TemplateArgument Kind!"); } +clang::TemplateArgumentLocInfo::TemplateArgumentLocInfo( + ASTContext &Ctx, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateNameLoc, SourceLocation EllipsisLoc) { + TemplateTemplateArgLocInfo *Template = new (Ctx) TemplateTemplateArgLocInfo; + Template->Qualifier = QualifierLoc.getNestedNameSpecifier(); + Template->QualifierLocData = QualifierLoc.getOpaqueData(); + Template->TemplateNameLoc = TemplateNameLoc.getRawEncoding(); + Template->EllipsisLoc = EllipsisLoc.getRawEncoding(); + Pointer = Template; +} + const ASTTemplateArgumentListInfo * ASTTemplateArgumentListInfo::Create(const ASTContext &C, const TemplateArgumentListInfo &List) { diff --git a/clang/lib/AST/TypeLoc.cpp b/clang/lib/AST/TypeLoc.cpp --- a/clang/lib/AST/TypeLoc.cpp +++ b/clang/lib/AST/TypeLoc.cpp @@ -582,7 +582,7 @@ Builder.MakeTrivial(Context, QTN->getQualifier(), Loc); ArgInfos[i] = TemplateArgumentLocInfo( - Builder.getWithLocInContext(Context), Loc, + Context, Builder.getWithLocInContext(Context), Loc, Args[i].getKind() == TemplateArgument::Template ? SourceLocation() : Loc); break; diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -938,11 +938,10 @@ TArg = TemplateArgument(Template, Optional()); else TArg = Template; - return TemplateArgumentLoc(TArg, - Arg.getScopeSpec().getWithLocInContext( - SemaRef.Context), - Arg.getLocation(), - Arg.getEllipsisLoc()); + return TemplateArgumentLoc( + SemaRef.Context, TArg, + Arg.getScopeSpec().getWithLocInContext(SemaRef.Context), + Arg.getLocation(), Arg.getEllipsisLoc()); } } @@ -5271,15 +5270,17 @@ if (TName.isNull()) return TemplateArgumentLoc(); - return TemplateArgumentLoc(TemplateArgument(TName), - TempTempParm->getDefaultArgument().getTemplateQualifierLoc(), - TempTempParm->getDefaultArgument().getTemplateNameLoc()); + return TemplateArgumentLoc( + Context, TemplateArgument(TName), + TempTempParm->getDefaultArgument().getTemplateQualifierLoc(), + TempTempParm->getDefaultArgument().getTemplateNameLoc()); } /// Convert a template-argument that we parsed as a type into a template, if /// possible. C++ permits injected-class-names to perform dual service as /// template template arguments and as template type arguments. -static TemplateArgumentLoc convertTypeTemplateArgumentToTemplate(TypeLoc TLoc) { +static TemplateArgumentLoc +convertTypeTemplateArgumentToTemplate(ASTContext &Context, TypeLoc TLoc) { // Extract and step over any surrounding nested-name-specifier. NestedNameSpecifierLoc QualLoc; if (auto ETLoc = TLoc.getAs()) { @@ -5289,11 +5290,10 @@ QualLoc = ETLoc.getQualifierLoc(); TLoc = ETLoc.getNamedTypeLoc(); } - // If this type was written as an injected-class-name, it can be used as a // template template argument. if (auto InjLoc = TLoc.getAs()) - return TemplateArgumentLoc(InjLoc.getTypePtr()->getTemplateName(), + return TemplateArgumentLoc(Context, InjLoc.getTypePtr()->getTemplateName(), QualLoc, InjLoc.getNameLoc()); // If this type was written as an injected-class-name, it may have been @@ -5303,7 +5303,8 @@ if (auto RecLoc = TLoc.getAs()) if (auto *CTSD = dyn_cast(RecLoc.getDecl())) - return TemplateArgumentLoc(TemplateName(CTSD->getSpecializedTemplate()), + return TemplateArgumentLoc(Context, + TemplateName(CTSD->getSpecializedTemplate()), QualLoc, RecLoc.getNameLoc()); return TemplateArgumentLoc(); @@ -5542,7 +5543,7 @@ // itself. if (Arg.getArgument().getKind() == TemplateArgument::Type) { TemplateArgumentLoc ConvertedArg = convertTypeTemplateArgumentToTemplate( - Arg.getTypeSourceInfo()->getTypeLoc()); + Context, Arg.getTypeSourceInfo()->getTypeLoc()); if (!ConvertedArg.getArgument().isNull()) Arg = ConvertedArg; } @@ -5861,8 +5862,9 @@ if (Name.isNull()) return true; - Arg = TemplateArgumentLoc(TemplateArgument(Name), QualifierLoc, - TempParm->getDefaultArgument().getTemplateNameLoc()); + Arg = TemplateArgumentLoc( + Context, TemplateArgument(Name), QualifierLoc, + TempParm->getDefaultArgument().getTemplateNameLoc()); } // Introduce an instantiation record that describes where we are using diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -2670,11 +2670,11 @@ Builder.MakeTrivial(Context, QTN->getQualifier(), Loc); if (Arg.getKind() == TemplateArgument::Template) - return TemplateArgumentLoc(Arg, Builder.getWithLocInContext(Context), - Loc); + return TemplateArgumentLoc(Context, Arg, + Builder.getWithLocInContext(Context), Loc); - return TemplateArgumentLoc(Arg, Builder.getWithLocInContext(Context), - Loc, Loc); + return TemplateArgumentLoc( + Context, Arg, Builder.getWithLocInContext(Context), Loc, Loc); } case TemplateArgument::Expression: diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2915,7 +2915,7 @@ if (!TName.isNull()) Param->setDefaultArgument( SemaRef.Context, - TemplateArgumentLoc(TemplateArgument(TName), + TemplateArgumentLoc(SemaRef.Context, TemplateArgument(TName), D->getDefaultArgument().getTemplateQualifierLoc(), D->getDefaultArgument().getTemplateNameLoc())); } diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -1095,7 +1095,7 @@ case TemplateArgument::TemplateExpansion: Ellipsis = OrigLoc.getTemplateEllipsisLoc(); NumExpansions = Argument.getNumTemplateExpansions(); - return TemplateArgumentLoc(Argument.getPackExpansionPattern(), + return TemplateArgumentLoc(Context, Argument.getPackExpansionPattern(), OrigLoc.getTemplateQualifierLoc(), OrigLoc.getTemplateNameLoc()); diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -3546,12 +3546,12 @@ } case TemplateArgument::Template: - return TemplateArgumentLoc(TemplateArgument( - Pattern.getArgument().getAsTemplate(), - NumExpansions), - Pattern.getTemplateQualifierLoc(), - Pattern.getTemplateNameLoc(), - EllipsisLoc); + return TemplateArgumentLoc( + SemaRef.Context, + TemplateArgument(Pattern.getArgument().getAsTemplate(), + NumExpansions), + Pattern.getTemplateQualifierLoc(), Pattern.getTemplateNameLoc(), + EllipsisLoc); case TemplateArgument::Null: case TemplateArgument::Integral: @@ -4289,8 +4289,8 @@ if (Template.isNull()) return true; - Output = TemplateArgumentLoc(TemplateArgument(Template), QualifierLoc, - Input.getTemplateNameLoc()); + Output = TemplateArgumentLoc(SemaRef.Context, TemplateArgument(Template), + QualifierLoc, Input.getTemplateNameLoc()); return false; } diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -7095,15 +7095,15 @@ NestedNameSpecifierLoc QualifierLoc = readNestedNameSpecifierLoc(); SourceLocation TemplateNameLoc = readSourceLocation(); - return TemplateArgumentLocInfo(QualifierLoc, TemplateNameLoc, - SourceLocation()); + return TemplateArgumentLocInfo(getASTContext(), QualifierLoc, + TemplateNameLoc, SourceLocation()); } case TemplateArgument::TemplateExpansion: { NestedNameSpecifierLoc QualifierLoc = readNestedNameSpecifierLoc(); SourceLocation TemplateNameLoc = readSourceLocation(); SourceLocation EllipsisLoc = readSourceLocation(); - return TemplateArgumentLocInfo(QualifierLoc, TemplateNameLoc, - EllipsisLoc); + return TemplateArgumentLocInfo(getASTContext(), QualifierLoc, + TemplateNameLoc, EllipsisLoc); } case TemplateArgument::Null: case TemplateArgument::Integral: