aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST')
-rw-r--r--clang/lib/AST/APValue.cpp3
-rw-r--r--clang/lib/AST/ASTConcept.cpp11
-rw-r--r--clang/lib/AST/ASTContext.cpp1079
-rw-r--r--clang/lib/AST/ASTDiagnostic.cpp49
-rw-r--r--clang/lib/AST/ASTDumper.cpp4
-rw-r--r--clang/lib/AST/ASTImporter.cpp302
-rw-r--r--clang/lib/AST/ASTImporterLookupTable.cpp16
-rw-r--r--clang/lib/AST/ASTStructuralEquivalence.cpp186
-rw-r--r--clang/lib/AST/ASTTypeTraits.cpp36
-rw-r--r--clang/lib/AST/ByteCode/Compiler.cpp61
-rw-r--r--clang/lib/AST/ByteCode/Compiler.h2
-rw-r--r--clang/lib/AST/ByteCode/Context.cpp4
-rw-r--r--clang/lib/AST/ByteCode/Context.h19
-rw-r--r--clang/lib/AST/ByteCode/Descriptor.cpp105
-rw-r--r--clang/lib/AST/ByteCode/Descriptor.h16
-rw-r--r--clang/lib/AST/ByteCode/Disasm.cpp11
-rw-r--r--clang/lib/AST/ByteCode/DynamicAllocator.cpp62
-rw-r--r--clang/lib/AST/ByteCode/DynamicAllocator.h9
-rw-r--r--clang/lib/AST/ByteCode/EvalEmitter.cpp7
-rw-r--r--clang/lib/AST/ByteCode/Interp.cpp254
-rw-r--r--clang/lib/AST/ByteCode/Interp.h54
-rw-r--r--clang/lib/AST/ByteCode/InterpBlock.cpp9
-rw-r--r--clang/lib/AST/ByteCode/InterpBlock.h58
-rw-r--r--clang/lib/AST/ByteCode/InterpBuiltin.cpp26
-rw-r--r--clang/lib/AST/ByteCode/InterpFrame.cpp11
-rw-r--r--clang/lib/AST/ByteCode/InterpFrame.h1
-rw-r--r--clang/lib/AST/ByteCode/InterpState.cpp22
-rw-r--r--clang/lib/AST/ByteCode/MemberPointer.h6
-rw-r--r--clang/lib/AST/ByteCode/Pointer.cpp7
-rw-r--r--clang/lib/AST/ByteCode/Pointer.h9
-rw-r--r--clang/lib/AST/ByteCode/Program.cpp13
-rw-r--r--clang/lib/AST/ByteCode/Record.cpp2
-rw-r--r--clang/lib/AST/CXXInheritance.cpp16
-rw-r--r--clang/lib/AST/Comment.cpp2
-rw-r--r--clang/lib/AST/CommentParser.cpp5
-rw-r--r--clang/lib/AST/CommentSema.cpp21
-rw-r--r--clang/lib/AST/ComparisonCategories.cpp2
-rw-r--r--clang/lib/AST/ComputeDependence.cpp26
-rw-r--r--clang/lib/AST/Decl.cpp110
-rw-r--r--clang/lib/AST/DeclBase.cpp40
-rw-r--r--clang/lib/AST/DeclCXX.cpp104
-rw-r--r--clang/lib/AST/DeclPrinter.cpp60
-rw-r--r--clang/lib/AST/DeclTemplate.cpp72
-rw-r--r--clang/lib/AST/DeclarationName.cpp6
-rw-r--r--clang/lib/AST/DynamicRecursiveASTVisitor.cpp53
-rw-r--r--clang/lib/AST/Expr.cpp25
-rw-r--r--clang/lib/AST/ExprCXX.cpp9
-rw-r--r--clang/lib/AST/ExprConcepts.cpp4
-rw-r--r--clang/lib/AST/ExprConstant.cpp103
-rw-r--r--clang/lib/AST/FormatString.cpp10
-rw-r--r--clang/lib/AST/InheritViz.cpp6
-rw-r--r--clang/lib/AST/ItaniumCXXABI.cpp8
-rw-r--r--clang/lib/AST/ItaniumMangle.cpp194
-rw-r--r--clang/lib/AST/JSONNodeDumper.cpp36
-rw-r--r--clang/lib/AST/MicrosoftMangle.cpp21
-rw-r--r--clang/lib/AST/NestedNameSpecifier.cpp474
-rw-r--r--clang/lib/AST/ODRHash.cpp124
-rw-r--r--clang/lib/AST/OpenACCClause.cpp7
-rw-r--r--clang/lib/AST/OpenMPClause.cpp26
-rw-r--r--clang/lib/AST/ParentMapContext.cpp6
-rw-r--r--clang/lib/AST/PrintfFormatString.cpp2
-rw-r--r--clang/lib/AST/QualTypeNames.cpp368
-rw-r--r--clang/lib/AST/RecordLayoutBuilder.cpp27
-rw-r--r--clang/lib/AST/ScanfFormatString.cpp5
-rw-r--r--clang/lib/AST/StmtPrinter.cpp33
-rw-r--r--clang/lib/AST/StmtProfile.cpp21
-rw-r--r--clang/lib/AST/TemplateBase.cpp32
-rw-r--r--clang/lib/AST/TemplateName.cpp56
-rw-r--r--clang/lib/AST/TextNodeDumper.cpp78
-rw-r--r--clang/lib/AST/Type.cpp474
-rw-r--r--clang/lib/AST/TypeLoc.cpp244
-rw-r--r--clang/lib/AST/TypePrinter.cpp261
-rw-r--r--clang/lib/AST/VTTBuilder.cpp12
-rw-r--r--clang/lib/AST/VTableBuilder.cpp8
74 files changed, 2873 insertions, 2772 deletions
diff --git a/clang/lib/AST/APValue.cpp b/clang/lib/AST/APValue.cpp
index ee3dc84..2d62209 100644
--- a/clang/lib/AST/APValue.cpp
+++ b/clang/lib/AST/APValue.cpp
@@ -902,8 +902,9 @@ void APValue::printPretty(raw_ostream &Out, const PrintingPolicy &Policy,
}
case APValue::Struct: {
Out << '{';
- const RecordDecl *RD = Ty->castAs<RecordType>()->getDecl();
bool First = true;
+ const RecordDecl *RD =
+ Ty->castAs<RecordType>()->getOriginalDecl()->getDefinitionOrSelf();
if (unsigned N = getStructNumBases()) {
const CXXRecordDecl *CD = cast<CXXRecordDecl>(RD);
CXXRecordDecl::base_class_const_iterator BI = CD->bases_begin();
diff --git a/clang/lib/AST/ASTConcept.cpp b/clang/lib/AST/ASTConcept.cpp
index 2243ac0..d658890 100644
--- a/clang/lib/AST/ASTConcept.cpp
+++ b/clang/lib/AST/ASTConcept.cpp
@@ -14,6 +14,7 @@
#include "clang/AST/ASTConcept.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ExprConcepts.h"
+#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/PrettyPrinter.h"
#include "llvm/ADT/StringExtras.h"
@@ -92,10 +93,16 @@ ConceptReference::Create(const ASTContext &C, NestedNameSpecifierLoc NNS,
FoundDecl, NamedConcept, ArgsAsWritten);
}
+SourceLocation ConceptReference::getBeginLoc() const {
+ // Note that if the qualifier is null the template KW must also be null.
+ if (auto QualifierLoc = getNestedNameSpecifierLoc())
+ return QualifierLoc.getBeginLoc();
+ return getConceptNameInfo().getBeginLoc();
+}
+
void ConceptReference::print(llvm::raw_ostream &OS,
const PrintingPolicy &Policy) const {
- if (NestedNameSpec)
- NestedNameSpec.getNestedNameSpecifier()->print(OS, Policy);
+ NestedNameSpec.getNestedNameSpecifier().print(OS, Policy);
ConceptName.printName(OS, Policy);
if (hasExplicitTemplateArgs()) {
OS << "<";
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 3a16111..95dd426 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -654,7 +654,7 @@ comments::FullComment *ASTContext::getCommentForDecl(
// does not have one of its own.
QualType QT = TD->getUnderlyingType();
if (const auto *TT = QT->getAs<TagType>())
- if (const Decl *TD = TT->getDecl())
+ if (const Decl *TD = TT->getOriginalDecl())
if (comments::FullComment *FC = getCommentForDecl(TD, PP))
return cloneFullComment(FC, D);
}
@@ -1933,10 +1933,12 @@ TypeInfoChars ASTContext::getTypeInfoDataSizeInChars(QualType T) const {
// of a base-class subobject. We decide whether that's possible
// during class layout, so here we can just trust the layout results.
if (getLangOpts().CPlusPlus) {
- if (const auto *RT = T->getAs<RecordType>();
- RT && !RT->getDecl()->isInvalidDecl()) {
- const ASTRecordLayout &layout = getASTRecordLayout(RT->getDecl());
- Info.Width = layout.getDataSize();
+ if (const auto *RT = T->getAs<RecordType>()) {
+ const auto *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
+ if (!RD->isInvalidDecl()) {
+ const ASTRecordLayout &layout = getASTRecordLayout(RD);
+ Info.Width = layout.getDataSize();
+ }
}
}
@@ -2003,8 +2005,9 @@ bool ASTContext::isPromotableIntegerType(QualType T) const {
// Enumerated types are promotable to their compatible integer types
// (C99 6.3.1.1) a.k.a. its underlying type (C++ [conv.prom]p2).
if (const auto *ET = T->getAs<EnumType>()) {
- if (T->isDependentType() || ET->getDecl()->getPromotionType().isNull() ||
- ET->getDecl()->isScoped())
+ const EnumDecl *ED = ET->getOriginalDecl()->getDefinitionOrSelf();
+ if (T->isDependentType() || ED->getPromotionType().isNull() ||
+ ED->isScoped())
return false;
return true;
@@ -2040,8 +2043,8 @@ unsigned ASTContext::getTypeAlignIfKnown(QualType T,
return Align;
// Otherwise, see if the declaration of the type had an attribute.
- if (const auto *TT = T->getAs<TagType>())
- return TT->getDecl()->getMaxAlignment();
+ if (const auto *TD = T->getAsTagDecl())
+ return TD->getMaxAlignment();
return 0;
}
@@ -2472,15 +2475,16 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
case Type::Record:
case Type::Enum: {
const auto *TT = cast<TagType>(T);
+ const TagDecl *TD = TT->getOriginalDecl()->getDefinitionOrSelf();
- if (TT->getDecl()->isInvalidDecl()) {
+ if (TD->isInvalidDecl()) {
Width = 8;
Align = 8;
break;
}
- if (const auto *ET = dyn_cast<EnumType>(TT)) {
- const EnumDecl *ED = ET->getDecl();
+ if (isa<EnumType>(TT)) {
+ const EnumDecl *ED = cast<EnumDecl>(TD);
TypeInfo Info =
getTypeInfo(ED->getIntegerType()->getUnqualifiedDesugaredType());
if (unsigned AttrAlign = ED->getMaxAlignment()) {
@@ -2490,8 +2494,7 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
return Info;
}
- const auto *RT = cast<RecordType>(TT);
- const RecordDecl *RD = RT->getDecl();
+ const auto *RD = cast<RecordDecl>(TD);
const ASTRecordLayout &Layout = getASTRecordLayout(RD);
Width = toBits(Layout.getSize());
Align = toBits(Layout.getAlignment());
@@ -2543,9 +2546,6 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
break;
}
- case Type::Elaborated:
- return getTypeInfo(cast<ElaboratedType>(T)->getNamedType().getTypePtr());
-
case Type::Attributed:
return getTypeInfo(
cast<AttributedType>(T)->getEquivalentType().getTypePtr());
@@ -2619,8 +2619,7 @@ unsigned ASTContext::getTypeUnadjustedAlign(const Type *T) const {
unsigned UnadjustedAlign;
if (const auto *RT = T->getAs<RecordType>()) {
- const RecordDecl *RD = RT->getDecl();
- const ASTRecordLayout &Layout = getASTRecordLayout(RD);
+ const ASTRecordLayout &Layout = getASTRecordLayout(RT->getOriginalDecl());
UnadjustedAlign = toBits(Layout.getUnadjustedAlignment());
} else if (const auto *ObjCI = T->getAs<ObjCInterfaceType>()) {
const ASTRecordLayout &Layout = getASTObjCInterfaceLayout(ObjCI->getDecl());
@@ -2696,7 +2695,7 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) const {
return ABIAlign;
if (const auto *RT = T->getAs<RecordType>()) {
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
// When used as part of a typedef, or together with a 'packed' attribute,
// the 'aligned' attribute can be used to decrease alignment. Note that the
@@ -2719,7 +2718,10 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) const {
if (const auto *CT = T->getAs<ComplexType>())
T = CT->getElementType().getTypePtr();
if (const auto *ET = T->getAs<EnumType>())
- T = ET->getDecl()->getIntegerType().getTypePtr();
+ T = ET->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->getIntegerType()
+ .getTypePtr();
if (T->isSpecificBuiltinType(BuiltinType::Double) ||
T->isSpecificBuiltinType(BuiltinType::LongLong) ||
T->isSpecificBuiltinType(BuiltinType::ULongLong) ||
@@ -2851,7 +2853,8 @@ static bool unionHasUniqueObjectRepresentations(const ASTContext &Context,
const RecordDecl *RD,
bool CheckIfTriviallyCopyable) {
assert(RD->isUnion() && "Must be union type");
- CharUnits UnionSize = Context.getTypeSizeInChars(RD->getTypeForDecl());
+ CharUnits UnionSize =
+ Context.getTypeSizeInChars(Context.getCanonicalTagType(RD));
for (const auto *Field : RD->fields()) {
if (!Context.hasUniqueObjectRepresentations(Field->getType(),
@@ -3045,7 +3048,8 @@ bool ASTContext::hasUniqueObjectRepresentations(
return !ABI->getMemberPointerInfo(MPT).HasPadding;
if (Ty->isRecordType()) {
- const RecordDecl *Record = Ty->castAs<RecordType>()->getDecl();
+ const RecordDecl *Record =
+ Ty->castAs<RecordType>()->getOriginalDecl()->getDefinitionOrSelf();
if (Record->isInvalidDecl())
return false;
@@ -3418,7 +3422,10 @@ static void encodeTypeForFunctionPointerAuth(const ASTContext &Ctx,
// type, or an unsigned integer type.
//
// So we have to treat enum types as integers.
- QualType UnderlyingType = cast<EnumType>(T)->getDecl()->getIntegerType();
+ QualType UnderlyingType = cast<EnumType>(T)
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->getIntegerType();
return encodeTypeForFunctionPointerAuth(
Ctx, OS, UnderlyingType.isNull() ? Ctx.IntTy : UnderlyingType);
}
@@ -3456,7 +3463,7 @@ static void encodeTypeForFunctionPointerAuth(const ASTContext &Ctx,
OS << "M";
const auto *MPT = T->castAs<MemberPointerType>();
encodeTypeForFunctionPointerAuth(
- Ctx, OS, QualType(MPT->getQualifier()->getAsType(), 0));
+ Ctx, OS, QualType(MPT->getQualifier().getAsType(), 0));
encodeTypeForFunctionPointerAuth(Ctx, OS, MPT->getPointeeType());
return;
}
@@ -3562,7 +3569,8 @@ static void encodeTypeForFunctionPointerAuth(const ASTContext &Ctx,
llvm_unreachable("should never get here");
}
case Type::Record: {
- const RecordDecl *RD = T->castAs<RecordType>()->getDecl();
+ const RecordDecl *RD =
+ T->castAs<RecordType>()->getOriginalDecl()->getDefinitionOrSelf();
const IdentifierInfo *II = RD->getIdentifier();
// In C++, an immediate typedef of an anonymous struct or union
@@ -3740,12 +3748,6 @@ ASTContext::adjustType(QualType Orig,
adjustType(BTFT->getWrappedType(), Adjust));
}
- case Type::Elaborated: {
- const auto *ET = cast<ElaboratedType>(Orig);
- return getElaboratedType(ET->getKeyword(), ET->getQualifier(),
- adjustType(ET->getNamedType(), Adjust));
- }
-
case Type::Paren:
return getParenType(
adjustType(cast<ParenType>(Orig)->getInnerType(), Adjust));
@@ -4163,14 +4165,13 @@ QualType ASTContext::getRValueReferenceType(QualType T) const {
}
QualType ASTContext::getMemberPointerType(QualType T,
- NestedNameSpecifier *Qualifier,
+ NestedNameSpecifier Qualifier,
const CXXRecordDecl *Cls) const {
if (!Qualifier) {
assert(Cls && "At least one of Qualifier or Cls must be provided");
- Qualifier = NestedNameSpecifier::Create(*this, /*Prefix=*/nullptr,
- getTypeDeclType(Cls).getTypePtr());
+ Qualifier = NestedNameSpecifier(getCanonicalTagType(Cls).getTypePtr());
} else if (!Cls) {
- Cls = Qualifier->getAsRecordDecl();
+ Cls = Qualifier.getAsRecordDecl();
}
// Unique pointers, to guarantee there is only one pointer of a particular
// structure.
@@ -4182,12 +4183,11 @@ QualType ASTContext::getMemberPointerType(QualType T,
MemberPointerTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(PT, 0);
- NestedNameSpecifier *CanonicalQualifier = [&] {
+ NestedNameSpecifier CanonicalQualifier = [&] {
if (!Cls)
- return getCanonicalNestedNameSpecifier(Qualifier);
- NestedNameSpecifier *R = NestedNameSpecifier::Create(
- *this, /*Prefix=*/nullptr, Cls->getCanonicalDecl()->getTypeForDecl());
- assert(R == getCanonicalNestedNameSpecifier(R));
+ return Qualifier.getCanonical();
+ NestedNameSpecifier R(getCanonicalTagType(Cls).getTypePtr());
+ assert(R.isCanonical());
return R;
}();
// If the pointee or class type isn't canonical, this won't be a canonical
@@ -5245,7 +5245,6 @@ ASTContext::getPredefinedSugarType(PredefinedSugarType::Kind KD) const {
}
llvm_unreachable("unexpected kind");
};
-
auto *New = new (*this, alignof(PredefinedSugarType))
PredefinedSugarType(KD, &Idents.get(PredefinedSugarType::getName(KD)),
getCanonicalType(*this, static_cast<Kind>(KD)));
@@ -5254,153 +5253,297 @@ ASTContext::getPredefinedSugarType(PredefinedSugarType::Kind KD) const {
return QualType(New, 0);
}
-#ifndef NDEBUG
-static bool NeedsInjectedClassNameType(const RecordDecl *D) {
- if (!isa<CXXRecordDecl>(D)) return false;
- const auto *RD = cast<CXXRecordDecl>(D);
- if (isa<ClassTemplatePartialSpecializationDecl>(RD))
- return true;
- if (RD->getDescribedClassTemplate() &&
- !isa<ClassTemplateSpecializationDecl>(RD))
- return true;
- return false;
-}
-#endif
+QualType ASTContext::getTypeDeclType(ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifier Qualifier,
+ const TypeDecl *Decl) const {
+ if (auto *Tag = dyn_cast<TagDecl>(Decl))
+ return getTagType(Keyword, Qualifier, Tag,
+ /*OwnsTag=*/false);
+ if (auto *Typedef = dyn_cast<TypedefNameDecl>(Decl))
+ return getTypedefType(Keyword, Qualifier, Typedef);
+ if (auto *UD = dyn_cast<UnresolvedUsingTypenameDecl>(Decl))
+ return getUnresolvedUsingType(Keyword, Qualifier, UD);
-/// getInjectedClassNameType - Return the unique reference to the
-/// injected class name type for the specified templated declaration.
-QualType ASTContext::getInjectedClassNameType(CXXRecordDecl *Decl,
- QualType TST) const {
- assert(NeedsInjectedClassNameType(Decl));
- if (Decl->TypeForDecl) {
- assert(isa<InjectedClassNameType>(Decl->TypeForDecl));
- } else if (CXXRecordDecl *PrevDecl = Decl->getPreviousDecl()) {
- assert(PrevDecl->TypeForDecl && "previous declaration has no type");
- Decl->TypeForDecl = PrevDecl->TypeForDecl;
- assert(isa<InjectedClassNameType>(Decl->TypeForDecl));
- } else {
- Type *newType = new (*this, alignof(InjectedClassNameType))
- InjectedClassNameType(Decl, TST);
- Decl->TypeForDecl = newType;
- Types.push_back(newType);
- }
+ assert(Keyword == ElaboratedTypeKeyword::None);
+ assert(!Qualifier);
return QualType(Decl->TypeForDecl, 0);
}
-/// getTypeDeclType - Return the unique reference to the type for the
-/// specified type declaration.
-QualType ASTContext::getTypeDeclTypeSlow(const TypeDecl *Decl) const {
- assert(Decl && "Passed null for Decl param");
- assert(!Decl->TypeForDecl && "TypeForDecl present in slow case");
-
- if (const auto *Typedef = dyn_cast<TypedefNameDecl>(Decl))
- return getTypedefType(Typedef);
-
- assert(!isa<TemplateTypeParmDecl>(Decl) &&
- "Template type parameter types are always available.");
-
- if (const auto *Record = dyn_cast<RecordDecl>(Decl)) {
- assert(Record->isFirstDecl() && "struct/union has previous declaration");
- assert(!NeedsInjectedClassNameType(Record));
- return getRecordType(Record);
- } else if (const auto *Enum = dyn_cast<EnumDecl>(Decl)) {
- assert(Enum->isFirstDecl() && "enum has previous declaration");
- return getEnumType(Enum);
- } else if (const auto *Using = dyn_cast<UnresolvedUsingTypenameDecl>(Decl)) {
- return getUnresolvedUsingType(Using);
- } else
- llvm_unreachable("TypeDecl without a type?");
-
+CanQualType ASTContext::getCanonicalTypeDeclType(const TypeDecl *TD) const {
+ if (auto *Tag = dyn_cast<TagDecl>(TD))
+ return getCanonicalTagType(Tag);
+ if (auto *TN = dyn_cast<TypedefNameDecl>(TD))
+ return getCanonicalType(TN->getUnderlyingType());
+ if (const auto *UD = dyn_cast<UnresolvedUsingTypenameDecl>(TD))
+ return getCanonicalUnresolvedUsingType(UD);
+ assert(TD->TypeForDecl);
+ return TD->TypeForDecl->getCanonicalTypeUnqualified();
+}
+
+QualType ASTContext::getTypeDeclType(const TypeDecl *Decl) const {
+ if (const auto *TD = dyn_cast<TagDecl>(Decl))
+ return getCanonicalTagType(TD);
+ if (const auto *TD = dyn_cast<TypedefNameDecl>(Decl);
+ isa_and_nonnull<TypedefDecl, TypeAliasDecl>(TD))
+ return getTypedefType(ElaboratedTypeKeyword::None,
+ /*Qualifier=*/std::nullopt, TD);
+ if (const auto *Using = dyn_cast<UnresolvedUsingTypenameDecl>(Decl))
+ return getCanonicalUnresolvedUsingType(Using);
+
+ assert(Decl->TypeForDecl);
return QualType(Decl->TypeForDecl, 0);
}
/// getTypedefType - Return the unique reference to the type for the
/// specified typedef name decl.
-QualType ASTContext::getTypedefType(const TypedefNameDecl *Decl,
- QualType Underlying) const {
- if (!Decl->TypeForDecl) {
- if (Underlying.isNull())
- Underlying = Decl->getUnderlyingType();
- auto *NewType = new (*this, alignof(TypedefType)) TypedefType(
- Type::Typedef, Decl, Underlying, /*HasTypeDifferentFromDecl=*/false);
- Decl->TypeForDecl = NewType;
+QualType
+ASTContext::getTypedefType(ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifier Qualifier,
+ const TypedefNameDecl *Decl, QualType UnderlyingType,
+ std::optional<bool> TypeMatchesDeclOrNone) const {
+ if (!TypeMatchesDeclOrNone) {
+ QualType DeclUnderlyingType = Decl->getUnderlyingType();
+ assert(!DeclUnderlyingType.isNull());
+ if (UnderlyingType.isNull())
+ UnderlyingType = DeclUnderlyingType;
+ else
+ assert(hasSameType(UnderlyingType, DeclUnderlyingType));
+ TypeMatchesDeclOrNone = UnderlyingType == DeclUnderlyingType;
+ } else {
+ // FIXME: This is a workaround for a serialization cycle: assume the decl
+ // underlying type is not available; don't touch it.
+ assert(!UnderlyingType.isNull());
+ }
+
+ if (Keyword == ElaboratedTypeKeyword::None && !Qualifier &&
+ *TypeMatchesDeclOrNone) {
+ if (Decl->TypeForDecl)
+ return QualType(Decl->TypeForDecl, 0);
+
+ auto *NewType = new (*this, alignof(TypedefType))
+ TypedefType(Type::Typedef, Keyword, Qualifier, Decl, UnderlyingType,
+ !*TypeMatchesDeclOrNone);
+
Types.push_back(NewType);
+ Decl->TypeForDecl = NewType;
return QualType(NewType, 0);
}
- if (Underlying.isNull() || Decl->getUnderlyingType() == Underlying)
- return QualType(Decl->TypeForDecl, 0);
- assert(hasSameType(Decl->getUnderlyingType(), Underlying));
llvm::FoldingSetNodeID ID;
- TypedefType::Profile(ID, Decl, Underlying);
+ TypedefType::Profile(ID, Keyword, Qualifier, Decl, UnderlyingType);
void *InsertPos = nullptr;
- if (TypedefType *T = TypedefTypes.FindNodeOrInsertPos(ID, InsertPos)) {
- assert(!T->typeMatchesDecl() &&
- "non-divergent case should be handled with TypeDecl");
- return QualType(T, 0);
- }
+ if (FoldingSetPlaceholder<TypedefType> *Placeholder =
+ TypedefTypes.FindNodeOrInsertPos(ID, InsertPos))
+ return QualType(Placeholder->getType(), 0);
- void *Mem = Allocate(TypedefType::totalSizeToAlloc<QualType>(true),
- alignof(TypedefType));
- auto *NewType = new (Mem) TypedefType(Type::Typedef, Decl, Underlying,
- /*HasTypeDifferentFromDecl=*/true);
- TypedefTypes.InsertNode(NewType, InsertPos);
+ void *Mem =
+ Allocate(TypedefType::totalSizeToAlloc<FoldingSetPlaceholder<TypedefType>,
+ NestedNameSpecifier, QualType>(
+ 1, !!Qualifier, !*TypeMatchesDeclOrNone),
+ alignof(TypedefType));
+ auto *NewType =
+ new (Mem) TypedefType(Type::Typedef, Keyword, Qualifier, Decl,
+ UnderlyingType, !*TypeMatchesDeclOrNone);
+ auto *Placeholder = new (NewType->getFoldingSetPlaceholder())
+ FoldingSetPlaceholder<TypedefType>();
+ TypedefTypes.InsertNode(Placeholder, InsertPos);
Types.push_back(NewType);
return QualType(NewType, 0);
}
-QualType ASTContext::getUsingType(const UsingShadowDecl *Found,
- QualType Underlying) const {
+QualType ASTContext::getUsingType(ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifier Qualifier,
+ const UsingShadowDecl *D,
+ QualType UnderlyingType) const {
+ // FIXME: This is expensive to compute every time!
+ if (UnderlyingType.isNull()) {
+ const auto *UD = cast<UsingDecl>(D->getIntroducer());
+ UnderlyingType =
+ getTypeDeclType(UD->hasTypename() ? ElaboratedTypeKeyword::Typename
+ : ElaboratedTypeKeyword::None,
+ UD->getQualifier(), cast<TypeDecl>(D->getTargetDecl()));
+ }
+
llvm::FoldingSetNodeID ID;
- UsingType::Profile(ID, Found, Underlying);
+ UsingType::Profile(ID, Keyword, Qualifier, D, UnderlyingType);
void *InsertPos = nullptr;
- if (UsingType *T = UsingTypes.FindNodeOrInsertPos(ID, InsertPos))
+ if (const UsingType *T = UsingTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(T, 0);
- const Type *TypeForDecl =
- cast<TypeDecl>(Found->getTargetDecl())->getTypeForDecl();
+ assert(!UnderlyingType.hasLocalQualifiers());
- assert(!Underlying.hasLocalQualifiers());
- QualType Canon = Underlying->getCanonicalTypeInternal();
- assert(TypeForDecl->getCanonicalTypeInternal() == Canon);
+ assert(
+ hasSameType(getCanonicalTypeDeclType(cast<TypeDecl>(D->getTargetDecl())),
+ UnderlyingType));
- if (Underlying.getTypePtr() == TypeForDecl)
- Underlying = QualType();
void *Mem =
- Allocate(UsingType::totalSizeToAlloc<QualType>(!Underlying.isNull()),
+ Allocate(UsingType::totalSizeToAlloc<NestedNameSpecifier>(!!Qualifier),
alignof(UsingType));
- UsingType *NewType = new (Mem) UsingType(Found, Underlying, Canon);
- Types.push_back(NewType);
- UsingTypes.InsertNode(NewType, InsertPos);
- return QualType(NewType, 0);
+ UsingType *T = new (Mem) UsingType(Keyword, Qualifier, D, UnderlyingType);
+ Types.push_back(T);
+ UsingTypes.InsertNode(T, InsertPos);
+ return QualType(T, 0);
}
-QualType ASTContext::getRecordType(const RecordDecl *Decl) const {
- if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0);
+TagType *ASTContext::getTagTypeInternal(ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifier Qualifier,
+ const TagDecl *TD, bool OwnsTag,
+ bool IsInjected,
+ const Type *CanonicalType,
+ bool WithFoldingSetNode) const {
+ auto [TC, Size] = [&] {
+ switch (TD->getDeclKind()) {
+ case Decl::Enum:
+ static_assert(alignof(EnumType) == alignof(TagType));
+ return std::make_tuple(Type::Enum, sizeof(EnumType));
+ case Decl::ClassTemplatePartialSpecialization:
+ case Decl::ClassTemplateSpecialization:
+ case Decl::CXXRecord:
+ static_assert(alignof(RecordType) == alignof(TagType));
+ static_assert(alignof(InjectedClassNameType) == alignof(TagType));
+ if (cast<CXXRecordDecl>(TD)->hasInjectedClassType())
+ return std::make_tuple(Type::InjectedClassName,
+ sizeof(InjectedClassNameType));
+ [[fallthrough]];
+ case Decl::Record:
+ return std::make_tuple(Type::Record, sizeof(RecordType));
+ default:
+ llvm_unreachable("unexpected decl kind");
+ }
+ }();
- if (const RecordDecl *PrevDecl = Decl->getPreviousDecl())
- if (PrevDecl->TypeForDecl)
- return QualType(Decl->TypeForDecl = PrevDecl->TypeForDecl, 0);
+ if (Qualifier) {
+ static_assert(alignof(NestedNameSpecifier) <= alignof(TagType));
+ Size = llvm::alignTo(Size, alignof(NestedNameSpecifier)) +
+ sizeof(NestedNameSpecifier);
+ }
+ void *Mem;
+ if (WithFoldingSetNode) {
+ // FIXME: It would be more profitable to tail allocate the folding set node
+ // from the type, instead of the other way around, due to the greater
+ // alignment requirements of the type. But this makes it harder to deal with
+ // the different type node sizes. This would require either uniquing from
+ // different folding sets, or having the folding setaccept a
+ // contextual parameter which is not fixed at construction.
+ Mem = Allocate(
+ sizeof(TagTypeFoldingSetPlaceholder) +
+ TagTypeFoldingSetPlaceholder::getOffset() + Size,
+ std::max(alignof(TagTypeFoldingSetPlaceholder), alignof(TagType)));
+ auto *T = new (Mem) TagTypeFoldingSetPlaceholder();
+ Mem = T->getTagType();
+ } else {
+ Mem = Allocate(Size, alignof(TagType));
+ }
+
+ auto *T = [&, TC = TC]() -> TagType * {
+ switch (TC) {
+ case Type::Enum: {
+ assert(isa<EnumDecl>(TD));
+ auto *T = new (Mem) EnumType(TC, Keyword, Qualifier, TD, OwnsTag,
+ IsInjected, CanonicalType);
+ assert(reinterpret_cast<void *>(T) ==
+ reinterpret_cast<void *>(static_cast<TagType *>(T)) &&
+ "TagType must be the first base of EnumType");
+ return T;
+ }
+ case Type::Record: {
+ assert(isa<RecordDecl>(TD));
+ auto *T = new (Mem) RecordType(TC, Keyword, Qualifier, TD, OwnsTag,
+ IsInjected, CanonicalType);
+ assert(reinterpret_cast<void *>(T) ==
+ reinterpret_cast<void *>(static_cast<TagType *>(T)) &&
+ "TagType must be the first base of RecordType");
+ return T;
+ }
+ case Type::InjectedClassName: {
+ auto *T = new (Mem) InjectedClassNameType(Keyword, Qualifier, TD,
+ IsInjected, CanonicalType);
+ assert(reinterpret_cast<void *>(T) ==
+ reinterpret_cast<void *>(static_cast<TagType *>(T)) &&
+ "TagType must be the first base of InjectedClassNameType");
+ return T;
+ }
+ default:
+ llvm_unreachable("unexpected type class");
+ }
+ }();
+ assert(T->getKeyword() == Keyword);
+ assert(T->getQualifier() == Qualifier);
+ assert(T->getOriginalDecl() == TD);
+ assert(T->isInjected() == IsInjected);
+ assert(T->isTagOwned() == OwnsTag);
+ assert((T->isCanonicalUnqualified()
+ ? QualType()
+ : T->getCanonicalTypeInternal()) == QualType(CanonicalType, 0));
+ Types.push_back(T);
+ return T;
+}
- auto *newType = new (*this, alignof(RecordType)) RecordType(Decl);
- Decl->TypeForDecl = newType;
- Types.push_back(newType);
- return QualType(newType, 0);
+static bool getNonInjectedClassName(const TagDecl *&TD) {
+ if (const auto *RD = dyn_cast<CXXRecordDecl>(TD);
+ RD && RD->isInjectedClassName()) {
+ TD = cast<TagDecl>(RD->getDeclContext());
+ return true;
+ }
+ return false;
}
-QualType ASTContext::getEnumType(const EnumDecl *Decl) const {
- if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0);
+CanQualType ASTContext::getCanonicalTagType(const TagDecl *TD) const {
+ ::getNonInjectedClassName(TD);
+ TD = TD->getCanonicalDecl();
+ if (TD->TypeForDecl)
+ return TD->TypeForDecl->getCanonicalTypeUnqualified();
+
+ const Type *CanonicalType = getTagTypeInternal(
+ ElaboratedTypeKeyword::None,
+ /*Qualifier=*/std::nullopt, TD,
+ /*OwnsTag=*/false, /*IsInjected=*/false, /*CanonicalType=*/nullptr,
+ /*WithFoldingSetNode=*/false);
+ TD->TypeForDecl = CanonicalType;
+ return CanQualType::CreateUnsafe(QualType(CanonicalType, 0));
+}
+
+QualType ASTContext::getTagType(ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifier Qualifier,
+ const TagDecl *TD, bool OwnsTag) const {
+ ElaboratedTypeKeyword PreferredKeyword =
+ getLangOpts().CPlusPlus
+ ? ElaboratedTypeKeyword::None
+ : KeywordHelpers::getKeywordForTagTypeKind(TD->getTagKind());
+
+ if (Keyword == PreferredKeyword && !Qualifier && !OwnsTag) {
+ if (const Type *T = TD->TypeForDecl; T && !T->isCanonicalUnqualified())
+ return QualType(T, 0);
+
+ bool IsInjected = ::getNonInjectedClassName(TD);
+ const Type *CanonicalType = getCanonicalTagType(TD).getTypePtr();
+ const Type *T =
+ getTagTypeInternal(Keyword,
+ /*Qualifier=*/std::nullopt, TD,
+ /*OwnsTag=*/false, IsInjected, CanonicalType,
+ /*WithFoldingSetNode=*/false);
+ TD->TypeForDecl = T;
+ return QualType(T, 0);
+ }
+
+ bool IsInjected = ::getNonInjectedClassName(TD);
- if (const EnumDecl *PrevDecl = Decl->getPreviousDecl())
- if (PrevDecl->TypeForDecl)
- return QualType(Decl->TypeForDecl = PrevDecl->TypeForDecl, 0);
+ llvm::FoldingSetNodeID ID;
+ TagTypeFoldingSetPlaceholder::Profile(ID, Keyword, Qualifier, TD, OwnsTag,
+ IsInjected);
- auto *newType = new (*this, alignof(EnumType)) EnumType(Decl);
- Decl->TypeForDecl = newType;
- Types.push_back(newType);
- return QualType(newType, 0);
+ void *InsertPos = nullptr;
+ if (TagTypeFoldingSetPlaceholder *T =
+ TagTypes.FindNodeOrInsertPos(ID, InsertPos))
+ return QualType(T->getTagType(), 0);
+
+ const Type *CanonicalType = getCanonicalTagType(TD).getTypePtr();
+ TagType *T = getTagTypeInternal(Keyword, Qualifier, TD, OwnsTag, IsInjected,
+ CanonicalType, /*WithFoldingSetNode=*/true);
+ TagTypes.InsertNode(TagTypeFoldingSetPlaceholder::fromTagType(T), InsertPos);
+ return QualType(T, 0);
}
bool ASTContext::computeBestEnumTypes(bool IsPacked, unsigned NumNegativeBits,
@@ -5495,21 +5638,69 @@ bool ASTContext::isRepresentableIntegerValue(llvm::APSInt &Value, QualType T) {
return Value.getSignificantBits() <= BitWidth;
}
-QualType ASTContext::getUnresolvedUsingType(
- const UnresolvedUsingTypenameDecl *Decl) const {
- if (Decl->TypeForDecl)
- return QualType(Decl->TypeForDecl, 0);
+UnresolvedUsingType *ASTContext::getUnresolvedUsingTypeInternal(
+ ElaboratedTypeKeyword Keyword, NestedNameSpecifier Qualifier,
+ const UnresolvedUsingTypenameDecl *D, void *InsertPos,
+ const Type *CanonicalType) const {
+ void *Mem = Allocate(
+ UnresolvedUsingType::totalSizeToAlloc<
+ FoldingSetPlaceholder<UnresolvedUsingType>, NestedNameSpecifier>(
+ !!InsertPos, !!Qualifier),
+ alignof(UnresolvedUsingType));
+ auto *T = new (Mem) UnresolvedUsingType(Keyword, Qualifier, D, CanonicalType);
+ if (InsertPos) {
+ auto *Placeholder = new (T->getFoldingSetPlaceholder())
+ FoldingSetPlaceholder<TypedefType>();
+ TypedefTypes.InsertNode(Placeholder, InsertPos);
+ }
+ Types.push_back(T);
+ return T;
+}
- if (const UnresolvedUsingTypenameDecl *CanonicalDecl =
- Decl->getCanonicalDecl())
- if (CanonicalDecl->TypeForDecl)
- return QualType(Decl->TypeForDecl = CanonicalDecl->TypeForDecl, 0);
+CanQualType ASTContext::getCanonicalUnresolvedUsingType(
+ const UnresolvedUsingTypenameDecl *D) const {
+ D = D->getCanonicalDecl();
+ if (D->TypeForDecl)
+ return D->TypeForDecl->getCanonicalTypeUnqualified();
- Type *newType =
- new (*this, alignof(UnresolvedUsingType)) UnresolvedUsingType(Decl);
- Decl->TypeForDecl = newType;
- Types.push_back(newType);
- return QualType(newType, 0);
+ const Type *CanonicalType = getUnresolvedUsingTypeInternal(
+ ElaboratedTypeKeyword::None,
+ /*Qualifier=*/std::nullopt, D,
+ /*InsertPos=*/nullptr, /*CanonicalType=*/nullptr);
+ D->TypeForDecl = CanonicalType;
+ return CanQualType::CreateUnsafe(QualType(CanonicalType, 0));
+}
+
+QualType
+ASTContext::getUnresolvedUsingType(ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifier Qualifier,
+ const UnresolvedUsingTypenameDecl *D) const {
+ if (Keyword == ElaboratedTypeKeyword::None && !Qualifier) {
+ if (const Type *T = D->TypeForDecl; T && !T->isCanonicalUnqualified())
+ return QualType(T, 0);
+
+ const Type *CanonicalType = getCanonicalUnresolvedUsingType(D).getTypePtr();
+ const Type *T =
+ getUnresolvedUsingTypeInternal(ElaboratedTypeKeyword::None,
+ /*Qualifier=*/std::nullopt, D,
+ /*InsertPos=*/nullptr, CanonicalType);
+ D->TypeForDecl = T;
+ return QualType(T, 0);
+ }
+
+ llvm::FoldingSetNodeID ID;
+ UnresolvedUsingType::Profile(ID, Keyword, Qualifier, D);
+
+ void *InsertPos = nullptr;
+ if (FoldingSetPlaceholder<UnresolvedUsingType> *Placeholder =
+ UnresolvedUsingTypes.FindNodeOrInsertPos(ID, InsertPos))
+ return QualType(Placeholder->getType(), 0);
+ assert(InsertPos);
+
+ const Type *CanonicalType = getCanonicalUnresolvedUsingType(D).getTypePtr();
+ const Type *T = getUnresolvedUsingTypeInternal(Keyword, Qualifier, D,
+ InsertPos, CanonicalType);
+ return QualType(T, 0);
}
QualType ASTContext::getAttributedType(attr::Kind attrKind,
@@ -5729,34 +5920,32 @@ QualType ASTContext::getTemplateTypeParmType(unsigned Depth, unsigned Index,
}
TypeSourceInfo *ASTContext::getTemplateSpecializationTypeInfo(
+ ElaboratedTypeKeyword Keyword, SourceLocation ElaboratedKeywordLoc,
+ NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKeywordLoc,
TemplateName Name, SourceLocation NameLoc,
const TemplateArgumentListInfo &SpecifiedArgs,
ArrayRef<TemplateArgument> CanonicalArgs, QualType Underlying) const {
- QualType TST = getTemplateSpecializationType(Name, SpecifiedArgs.arguments(),
- CanonicalArgs, Underlying);
+ QualType TST = getTemplateSpecializationType(
+ Keyword, Name, SpecifiedArgs.arguments(), CanonicalArgs, Underlying);
TypeSourceInfo *DI = CreateTypeSourceInfo(TST);
- TemplateSpecializationTypeLoc TL =
- DI->getTypeLoc().castAs<TemplateSpecializationTypeLoc>();
- TL.setTemplateKeywordLoc(SourceLocation());
- TL.setTemplateNameLoc(NameLoc);
- TL.setLAngleLoc(SpecifiedArgs.getLAngleLoc());
- TL.setRAngleLoc(SpecifiedArgs.getRAngleLoc());
- for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
- TL.setArgLocInfo(i, SpecifiedArgs[i].getLocInfo());
+ DI->getTypeLoc().castAs<TemplateSpecializationTypeLoc>().set(
+ ElaboratedKeywordLoc, QualifierLoc, TemplateKeywordLoc, NameLoc,
+ SpecifiedArgs);
return DI;
}
QualType ASTContext::getTemplateSpecializationType(
- TemplateName Template, ArrayRef<TemplateArgumentLoc> SpecifiedArgs,
+ ElaboratedTypeKeyword Keyword, TemplateName Template,
+ ArrayRef<TemplateArgumentLoc> SpecifiedArgs,
ArrayRef<TemplateArgument> CanonicalArgs, QualType Underlying) const {
SmallVector<TemplateArgument, 4> SpecifiedArgVec;
SpecifiedArgVec.reserve(SpecifiedArgs.size());
for (const TemplateArgumentLoc &Arg : SpecifiedArgs)
SpecifiedArgVec.push_back(Arg.getArgument());
- return getTemplateSpecializationType(Template, SpecifiedArgVec, CanonicalArgs,
- Underlying);
+ return getTemplateSpecializationType(Keyword, Template, SpecifiedArgVec,
+ CanonicalArgs, Underlying);
}
[[maybe_unused]] static bool
@@ -5787,7 +5976,8 @@ QualType ASTContext::getCanonicalTemplateSpecializationType(
sizeof(TemplateArgument) * Args.size(),
alignof(TemplateSpecializationType));
auto *Spec = new (Mem)
- TemplateSpecializationType(Template, /*IsAlias=*/false, Args, QualType());
+ TemplateSpecializationType(ElaboratedTypeKeyword::None, Template,
+ /*IsAlias=*/false, Args, QualType());
assert(Spec->isDependentType() &&
"canonical template specialization must be dependent");
Types.push_back(Spec);
@@ -5796,7 +5986,8 @@ QualType ASTContext::getCanonicalTemplateSpecializationType(
}
QualType ASTContext::getTemplateSpecializationType(
- TemplateName Template, ArrayRef<TemplateArgument> SpecifiedArgs,
+ ElaboratedTypeKeyword Keyword, TemplateName Template,
+ ArrayRef<TemplateArgument> SpecifiedArgs,
ArrayRef<TemplateArgument> CanonicalArgs, QualType Underlying) const {
assert(!Template.getUnderlying().getAsDependentTemplateName() &&
"No dependent template names here!");
@@ -5806,7 +5997,8 @@ QualType ASTContext::getTemplateSpecializationType(
if (Underlying.isNull()) {
TemplateName CanonTemplate =
getCanonicalTemplateName(Template, /*IgnoreDeduced=*/true);
- bool NonCanonical = Template != CanonTemplate;
+ bool NonCanonical =
+ Template != CanonTemplate || Keyword != ElaboratedTypeKeyword::None;
SmallVector<TemplateArgument, 4> CanonArgsVec;
if (CanonicalArgs.empty()) {
CanonArgsVec = SmallVector<TemplateArgument, 4>(SpecifiedArgs);
@@ -5837,42 +6029,12 @@ QualType ASTContext::getTemplateSpecializationType(
sizeof(TemplateArgument) * SpecifiedArgs.size() +
(IsTypeAlias ? sizeof(QualType) : 0),
alignof(TemplateSpecializationType));
- auto *Spec = new (Mem) TemplateSpecializationType(Template, IsTypeAlias,
- SpecifiedArgs, Underlying);
+ auto *Spec = new (Mem) TemplateSpecializationType(
+ Keyword, Template, IsTypeAlias, SpecifiedArgs, Underlying);
Types.push_back(Spec);
return QualType(Spec, 0);
}
-QualType ASTContext::getElaboratedType(ElaboratedTypeKeyword Keyword,
- NestedNameSpecifier *NNS,
- QualType NamedType,
- TagDecl *OwnedTagDecl) const {
- llvm::FoldingSetNodeID ID;
- ElaboratedType::Profile(ID, Keyword, NNS, NamedType, OwnedTagDecl);
-
- void *InsertPos = nullptr;
- ElaboratedType *T = ElaboratedTypes.FindNodeOrInsertPos(ID, InsertPos);
- if (T)
- return QualType(T, 0);
-
- QualType Canon = NamedType;
- if (!Canon.isCanonical()) {
- Canon = getCanonicalType(NamedType);
- ElaboratedType *CheckT = ElaboratedTypes.FindNodeOrInsertPos(ID, InsertPos);
- assert(!CheckT && "Elaborated canonical type broken");
- (void)CheckT;
- }
-
- void *Mem =
- Allocate(ElaboratedType::totalSizeToAlloc<TagDecl *>(!!OwnedTagDecl),
- alignof(ElaboratedType));
- T = new (Mem) ElaboratedType(Keyword, NNS, NamedType, Canon, OwnedTagDecl);
-
- Types.push_back(T);
- ElaboratedTypes.InsertNode(T, InsertPos);
- return QualType(T, 0);
-}
-
QualType
ASTContext::getParenType(QualType InnerType) const {
llvm::FoldingSetNodeID ID;
@@ -5935,7 +6097,7 @@ getCanonicalElaboratedTypeKeyword(ElaboratedTypeKeyword Keyword) {
}
QualType ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword,
- NestedNameSpecifier *NNS,
+ NestedNameSpecifier NNS,
const IdentifierInfo *Name) const {
llvm::FoldingSetNodeID ID;
DependentNameType::Profile(ID, Keyword, NNS, Name);
@@ -5947,7 +6109,7 @@ QualType ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword,
ElaboratedTypeKeyword CanonKeyword =
getCanonicalElaboratedTypeKeyword(Keyword);
- NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS);
+ NestedNameSpecifier CanonNNS = NNS.getCanonical();
QualType Canon;
if (CanonKeyword != Keyword || CanonNNS != NNS) {
@@ -5985,13 +6147,13 @@ QualType ASTContext::getDependentTemplateSpecializationType(
T_iter != DependentTemplateSpecializationTypes.end())
return QualType(T_iter->getSecond(), 0);
- NestedNameSpecifier *NNS = Name.getQualifier();
+ NestedNameSpecifier NNS = Name.getQualifier();
QualType Canon;
if (!IsCanonical) {
ElaboratedTypeKeyword CanonKeyword =
getCanonicalElaboratedTypeKeyword(Keyword);
- NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS);
+ NestedNameSpecifier CanonNNS = NNS.getCanonical();
bool AnyNonCanonArgs = false;
auto CanonArgs =
::getCanonicalTemplateArguments(*this, Args, AnyNonCanonArgs);
@@ -6006,7 +6168,7 @@ QualType ASTContext::getDependentTemplateSpecializationType(
} else {
assert(Keyword == getCanonicalElaboratedTypeKeyword(Keyword));
assert(Name.hasTemplateKeyword());
- assert(NNS == getCanonicalNestedNameSpecifier(NNS));
+ assert(NNS.isCanonical());
#ifndef NDEBUG
for (const auto &Arg : Args)
assert(Arg.structurallyEquals(getCanonicalTemplateArgument(Arg)));
@@ -6062,7 +6224,8 @@ TemplateArgument ASTContext::getInjectedTemplateArg(NamedDecl *Param) const {
} else {
auto *TTP = cast<TemplateTemplateParmDecl>(Param);
TemplateName Name = getQualifiedTemplateName(
- nullptr, /*TemplateKeyword=*/false, TemplateName(TTP));
+ /*Qualifier=*/std::nullopt, /*TemplateKeyword=*/false,
+ TemplateName(TTP));
if (TTP->isParameterPack())
Arg = TemplateArgument(Name, /*NumExpansions=*/std::nullopt);
else
@@ -6334,11 +6497,11 @@ void ASTContext::adjustObjCTypeParamBoundType(const ObjCTypeParamDecl *Orig,
ObjCTypeParamDecl *New) const {
New->setTypeSourceInfo(getTrivialTypeSourceInfo(Orig->getUnderlyingType()));
// Update TypeForDecl after updating TypeSourceInfo.
- auto NewTypeParamTy = cast<ObjCTypeParamType>(New->getTypeForDecl());
+ auto *NewTypeParamTy = cast<ObjCTypeParamType>(New->TypeForDecl);
SmallVector<ObjCProtocolDecl *, 8> protocols;
protocols.append(NewTypeParamTy->qual_begin(), NewTypeParamTy->qual_end());
QualType UpdatedTy = getObjCTypeParamType(New, protocols);
- New->setTypeForDecl(UpdatedTy.getTypePtr());
+ New->TypeForDecl = UpdatedTy.getTypePtr();
}
/// ObjCObjectAdoptsQTypeProtocols - Checks that protocols in IC's
@@ -6737,20 +6900,20 @@ QualType ASTContext::getUnconstrainedType(QualType T) const {
}
QualType ASTContext::getDeducedTemplateSpecializationTypeInternal(
- TemplateName Template, QualType DeducedType, bool IsDependent,
- QualType Canon) const {
+ ElaboratedTypeKeyword Keyword, TemplateName Template, QualType DeducedType,
+ bool IsDependent, QualType Canon) const {
// Look in the folding set for an existing type.
void *InsertPos = nullptr;
llvm::FoldingSetNodeID ID;
- DeducedTemplateSpecializationType::Profile(ID, Template, DeducedType,
+ DeducedTemplateSpecializationType::Profile(ID, Keyword, Template, DeducedType,
IsDependent);
if (DeducedTemplateSpecializationType *DTST =
DeducedTemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(DTST, 0);
auto *DTST = new (*this, alignof(DeducedTemplateSpecializationType))
- DeducedTemplateSpecializationType(Template, DeducedType, IsDependent,
- Canon);
+ DeducedTemplateSpecializationType(Keyword, Template, DeducedType,
+ IsDependent, Canon);
#ifndef NDEBUG
llvm::FoldingSetNodeID TempID;
@@ -6766,14 +6929,20 @@ QualType ASTContext::getDeducedTemplateSpecializationTypeInternal(
/// which has been deduced to the given type, or to the canonical undeduced
/// such type, or the canonical deduced-but-dependent such type.
QualType ASTContext::getDeducedTemplateSpecializationType(
- TemplateName Template, QualType DeducedType, bool IsDependent) const {
- QualType Canon = DeducedType.isNull()
- ? getDeducedTemplateSpecializationTypeInternal(
- getCanonicalTemplateName(Template), QualType(),
- IsDependent, QualType())
- : DeducedType.getCanonicalType();
- return getDeducedTemplateSpecializationTypeInternal(Template, DeducedType,
- IsDependent, Canon);
+ ElaboratedTypeKeyword Keyword, TemplateName Template, QualType DeducedType,
+ bool IsDependent) const {
+ // FIXME: This could save an extra hash table lookup if it handled all the
+ // parameters already being canonical.
+ // FIXME: Can this be formed from a DependentTemplateName, such that the
+ // keyword should be part of the canonical type?
+ QualType Canon =
+ DeducedType.isNull()
+ ? getDeducedTemplateSpecializationTypeInternal(
+ ElaboratedTypeKeyword::None, getCanonicalTemplateName(Template),
+ QualType(), IsDependent, QualType())
+ : DeducedType.getCanonicalType();
+ return getDeducedTemplateSpecializationTypeInternal(
+ Keyword, Template, DeducedType, IsDependent, Canon);
}
/// getAtomicType - Return the uniqued reference to the atomic type for
@@ -6823,15 +6992,6 @@ QualType ASTContext::getAutoRRefDeductType() const {
return AutoRRefDeductTy;
}
-/// getTagDeclType - Return the unique reference to the type for the
-/// specified TagDecl (struct/union/class/enum) decl.
-QualType ASTContext::getTagDeclType(const TagDecl *Decl) const {
- assert(Decl);
- // FIXME: What is the design on getTagDeclType when it requires casting
- // away const? mutable?
- return getTypeDeclType(const_cast<TagDecl*>(Decl));
-}
-
/// getSizeType - Return the unique type for "size_t" (C99 7.17), the result
/// of the sizeof operator (C99 6.5.3.4p4). The value is target dependent and
/// needs to agree with the definition in <stddef.h>.
@@ -7053,8 +7213,8 @@ bool ASTContext::UnwrapSimilarTypes(QualType &T1, QualType &T2,
*RD2 = T2MPType->getMostRecentCXXRecordDecl();
RD1 != RD2 && RD1->getCanonicalDecl() != RD2->getCanonicalDecl())
return false;
- if (getCanonicalNestedNameSpecifier(T1MPType->getQualifier()) !=
- getCanonicalNestedNameSpecifier(T2MPType->getQualifier()))
+ if (T1MPType->getQualifier().getCanonical() !=
+ T2MPType->getQualifier().getCanonical())
return false;
T1 = T1MPType->getPointeeType();
T2 = T2MPType->getPointeeType();
@@ -7211,9 +7371,8 @@ TemplateName ASTContext::getCanonicalTemplateName(TemplateName Name,
case TemplateName::DependentTemplate: {
DependentTemplateName *DTN = Name.getAsDependentTemplateName();
assert(DTN && "Non-dependent template names must refer to template decls.");
- NestedNameSpecifier *Qualifier = DTN->getQualifier();
- NestedNameSpecifier *CanonQualifier =
- getCanonicalNestedNameSpecifier(Qualifier);
+ NestedNameSpecifier Qualifier = DTN->getQualifier();
+ NestedNameSpecifier CanonQualifier = Qualifier.getCanonical();
if (Qualifier != CanonQualifier || !DTN->hasTemplateKeyword())
return getDependentTemplateName({CanonQualifier, DTN->getName(),
/*HasTemplateKeyword=*/true});
@@ -7430,38 +7589,40 @@ bool ASTContext::isSameDefaultTemplateArgument(const NamedDecl *X,
return hasSameTemplateName(TAX.getAsTemplate(), TAY.getAsTemplate());
}
-static bool isSameQualifier(const NestedNameSpecifier *X,
- const NestedNameSpecifier *Y) {
- if (X->getKind() != Y->getKind())
+static bool isSameQualifier(const NestedNameSpecifier X,
+ const NestedNameSpecifier Y) {
+ if (X == Y)
+ return true;
+ if (!X || !Y)
+ return false;
+
+ auto Kind = X.getKind();
+ if (Kind != Y.getKind())
return false;
// FIXME: For namespaces and types, we're permitted to check that the entity
// is named via the same tokens. We should probably do so.
- switch (X->getKind()) {
- case NestedNameSpecifier::Identifier:
- if (X->getAsIdentifier() != Y->getAsIdentifier())
- return false;
- break;
- case NestedNameSpecifier::Namespace:
- if (!declaresSameEntity(X->getAsNamespace(), Y->getAsNamespace()))
+ switch (Kind) {
+ case NestedNameSpecifier::Kind::Namespace: {
+ auto [NamespaceX, PrefixX] = X.getAsNamespaceAndPrefix();
+ auto [NamespaceY, PrefixY] = Y.getAsNamespaceAndPrefix();
+ if (!declaresSameEntity(NamespaceX->getNamespace(),
+ NamespaceY->getNamespace()))
return false;
- break;
- case NestedNameSpecifier::TypeSpec:
- if (X->getAsType()->getCanonicalTypeInternal() !=
- Y->getAsType()->getCanonicalTypeInternal())
+ return isSameQualifier(PrefixX, PrefixY);
+ }
+ case NestedNameSpecifier::Kind::Type: {
+ const auto *TX = X.getAsType(), *TY = Y.getAsType();
+ if (TX->getCanonicalTypeInternal() != TY->getCanonicalTypeInternal())
return false;
- break;
- case NestedNameSpecifier::Global:
- case NestedNameSpecifier::Super:
+ return isSameQualifier(TX->getPrefix(), TY->getPrefix());
+ }
+ case NestedNameSpecifier::Kind::Null:
+ case NestedNameSpecifier::Kind::Global:
+ case NestedNameSpecifier::Kind::MicrosoftSuper:
return true;
}
-
- // Recurse into earlier portion of NNS, if any.
- auto *PX = X->getPrefix();
- auto *PY = Y->getPrefix();
- if (PX && PY)
- return isSameQualifier(PX, PY);
- return !PX && !PY;
+ llvm_unreachable("unhandled qualifier kind");
}
static bool hasSameCudaAttrs(const FunctionDecl *A, const FunctionDecl *B) {
@@ -7854,63 +8015,6 @@ bool ASTContext::isSameTemplateArgument(const TemplateArgument &Arg1,
llvm_unreachable("Unhandled template argument kind");
}
-NestedNameSpecifier *
-ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const {
- if (!NNS)
- return nullptr;
-
- switch (NNS->getKind()) {
- case NestedNameSpecifier::Identifier:
- // Canonicalize the prefix but keep the identifier the same.
- return NestedNameSpecifier::Create(*this,
- getCanonicalNestedNameSpecifier(NNS->getPrefix()),
- NNS->getAsIdentifier());
-
- case NestedNameSpecifier::Namespace:
- // A namespace is canonical; build a nested-name-specifier with
- // this namespace and no prefix.
- return NestedNameSpecifier::Create(
- *this, nullptr, NNS->getAsNamespace()->getNamespace()->getFirstDecl());
-
- // The difference between TypeSpec and TypeSpecWithTemplate is that the
- // latter will have the 'template' keyword when printed.
- case NestedNameSpecifier::TypeSpec: {
- const Type *T = getCanonicalType(NNS->getAsType());
-
- // If we have some kind of dependent-named type (e.g., "typename T::type"),
- // break it apart into its prefix and identifier, then reconsititute those
- // as the canonical nested-name-specifier. This is required to canonicalize
- // a dependent nested-name-specifier involving typedefs of dependent-name
- // types, e.g.,
- // typedef typename T::type T1;
- // typedef typename T1::type T2;
- if (const auto *DNT = T->getAs<DependentNameType>())
- return NestedNameSpecifier::Create(*this, DNT->getQualifier(),
- DNT->getIdentifier());
- if (const auto *DTST = T->getAs<DependentTemplateSpecializationType>()) {
- const DependentTemplateStorage &DTN = DTST->getDependentTemplateName();
- QualType NewT = getDependentTemplateSpecializationType(
- ElaboratedTypeKeyword::None,
- {/*NNS=*/nullptr, DTN.getName(), /*HasTemplateKeyword=*/true},
- DTST->template_arguments(), /*IsCanonical=*/true);
- assert(NewT.isCanonical());
- NestedNameSpecifier *Prefix = DTN.getQualifier();
- if (!Prefix)
- Prefix = getCanonicalNestedNameSpecifier(NNS->getPrefix());
- return NestedNameSpecifier::Create(*this, Prefix, NewT.getTypePtr());
- }
- return NestedNameSpecifier::Create(*this, nullptr, T);
- }
-
- case NestedNameSpecifier::Global:
- case NestedNameSpecifier::Super:
- // The global specifier and __super specifer are canonical and unique.
- return NNS;
- }
-
- llvm_unreachable("Invalid NestedNameSpecifier::Kind!");
-}
-
const ArrayType *ASTContext::getAsArrayType(QualType T) const {
// Handle the non-qualified case efficiently.
if (!T.hasLocalQualifiers()) {
@@ -8229,7 +8333,7 @@ QualType ASTContext::getPromotedIntegerType(QualType Promotable) const {
assert(!Promotable.isNull());
assert(isPromotableIntegerType(Promotable));
if (const auto *ET = Promotable->getAs<EnumType>())
- return ET->getDecl()->getPromotionType();
+ return ET->getOriginalDecl()->getDefinitionOrSelf()->getPromotionType();
if (const auto *BT = Promotable->getAs<BuiltinType>()) {
// C++ [conv.prom]: A prvalue of type char16_t, char32_t, or wchar_t
@@ -8288,8 +8392,9 @@ Qualifiers::ObjCLifetime ASTContext::getInnerObjCOwnership(QualType T) const {
static const Type *getIntegerTypeForEnum(const EnumType *ET) {
// Incomplete enum types are not treated as integer types.
// FIXME: In C++, enum types are never integer types.
- if (ET->getDecl()->isComplete() && !ET->getDecl()->isScoped())
- return ET->getDecl()->getIntegerType().getTypePtr();
+ const EnumDecl *ED = ET->getOriginalDecl()->getDefinitionOrSelf();
+ if (ED->isComplete() && !ED->isScoped())
+ return ED->getIntegerType().getTypePtr();
return nullptr;
}
@@ -8418,7 +8523,7 @@ TypedefDecl *ASTContext::getCFConstantStringDecl() const {
CFConstantStringTagDecl->completeDefinition();
// This type is designed to be compatible with NSConstantString, but cannot
// use the same name, since NSConstantString is an interface.
- auto tagType = getTagDeclType(CFConstantStringTagDecl);
+ CanQualType tagType = getCanonicalTagType(CFConstantStringTagDecl);
CFConstantStringTypeDecl =
buildImplicitTypedef(tagType, "__NSConstantString");
@@ -8433,14 +8538,15 @@ RecordDecl *ASTContext::getCFConstantStringTagDecl() const {
// getCFConstantStringType - Return the type used for constant CFStrings.
QualType ASTContext::getCFConstantStringType() const {
- return getTypedefType(getCFConstantStringDecl());
+ return getTypedefType(ElaboratedTypeKeyword::None, /*Qualifier=*/std::nullopt,
+ getCFConstantStringDecl());
}
QualType ASTContext::getObjCSuperType() const {
if (ObjCSuperType.isNull()) {
RecordDecl *ObjCSuperTypeDecl = buildImplicitRecord("objc_super");
getTranslationUnitDecl()->addDecl(ObjCSuperTypeDecl);
- ObjCSuperType = getTagDeclType(ObjCSuperTypeDecl);
+ ObjCSuperType = getCanonicalTagType(ObjCSuperTypeDecl);
}
return ObjCSuperType;
}
@@ -8449,12 +8555,12 @@ void ASTContext::setCFConstantStringType(QualType T) {
const auto *TD = T->castAs<TypedefType>();
CFConstantStringTypeDecl = cast<TypedefDecl>(TD->getDecl());
const auto *TagType = TD->castAs<RecordType>();
- CFConstantStringTagDecl = TagType->getDecl();
+ CFConstantStringTagDecl = TagType->getOriginalDecl()->getDefinitionOrSelf();
}
QualType ASTContext::getBlockDescriptorType() const {
if (BlockDescriptorType)
- return getTagDeclType(BlockDescriptorType);
+ return getCanonicalTagType(BlockDescriptorType);
RecordDecl *RD;
// FIXME: Needs the FlagAppleBlock bit.
@@ -8484,12 +8590,12 @@ QualType ASTContext::getBlockDescriptorType() const {
BlockDescriptorType = RD;
- return getTagDeclType(BlockDescriptorType);
+ return getCanonicalTagType(BlockDescriptorType);
}
QualType ASTContext::getBlockDescriptorExtendedType() const {
if (BlockDescriptorExtendedType)
- return getTagDeclType(BlockDescriptorExtendedType);
+ return getCanonicalTagType(BlockDescriptorExtendedType);
RecordDecl *RD;
// FIXME: Needs the FlagAppleBlock bit.
@@ -8523,7 +8629,7 @@ QualType ASTContext::getBlockDescriptorExtendedType() const {
RD->completeDefinition();
BlockDescriptorExtendedType = RD;
- return getTagDeclType(BlockDescriptorExtendedType);
+ return getCanonicalTagType(BlockDescriptorExtendedType);
}
OpenCLTypeKind ASTContext::getOpenCLTypeKind(const Type *T) const {
@@ -9161,7 +9267,7 @@ static char getObjCEncodingForPrimitiveType(const ASTContext *C,
}
static char ObjCEncodingForEnumType(const ASTContext *C, const EnumType *ET) {
- EnumDecl *Enum = ET->getDecl();
+ EnumDecl *Enum = ET->getOriginalDecl()->getDefinitionOrSelf();
// The encoding of an non-fixed enum type is always 'i', regardless of size.
if (!Enum->isFixed())
@@ -9330,13 +9436,14 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string &S,
return;
}
} else if (const auto *RTy = PointeeTy->getAs<RecordType>()) {
+ const IdentifierInfo *II = RTy->getOriginalDecl()->getIdentifier();
// GCC binary compat: Need to convert "struct objc_class *" to "#".
- if (RTy->getDecl()->getIdentifier() == &Idents.get("objc_class")) {
+ if (II == &Idents.get("objc_class")) {
S += '#';
return;
}
// GCC binary compat: Need to convert "struct objc_object *" to "@".
- if (RTy->getDecl()->getIdentifier() == &Idents.get("objc_object")) {
+ if (II == &Idents.get("objc_object")) {
S += '@';
return;
}
@@ -9401,7 +9508,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string &S,
return;
case Type::Record: {
- RecordDecl *RDecl = cast<RecordType>(CT)->getDecl();
+ RecordDecl *RDecl = cast<RecordType>(CT)->getOriginalDecl();
S += RDecl->isUnion() ? '(' : '{';
// Anonymous structures print as '?'
if (const IdentifierInfo *II = RDecl->getIdentifier()) {
@@ -9900,7 +10007,7 @@ CreateAArch64ABIBuiltinVaListDecl(const ASTContext *Context) {
}
VaListTagDecl->completeDefinition();
Context->VaListTagDecl = VaListTagDecl;
- QualType VaListTagType = Context->getRecordType(VaListTagDecl);
+ CanQualType VaListTagType = Context->getCanonicalTagType(VaListTagDecl);
// } __builtin_va_list;
return Context->buildImplicitTypedef(VaListTagType, "__builtin_va_list");
@@ -9952,14 +10059,15 @@ static TypedefDecl *CreatePowerABIBuiltinVaListDecl(const ASTContext *Context) {
}
VaListTagDecl->completeDefinition();
Context->VaListTagDecl = VaListTagDecl;
- QualType VaListTagType = Context->getRecordType(VaListTagDecl);
+ CanQualType VaListTagType = Context->getCanonicalTagType(VaListTagDecl);
// } __va_list_tag;
TypedefDecl *VaListTagTypedefDecl =
Context->buildImplicitTypedef(VaListTagType, "__va_list_tag");
QualType VaListTagTypedefType =
- Context->getTypedefType(VaListTagTypedefDecl);
+ Context->getTypedefType(ElaboratedTypeKeyword::None,
+ /*Qualifier=*/std::nullopt, VaListTagTypedefDecl);
// typedef __va_list_tag __builtin_va_list[1];
llvm::APInt Size(Context->getTypeSize(Context->getSizeType()), 1);
@@ -10011,7 +10119,7 @@ CreateX86_64ABIBuiltinVaListDecl(const ASTContext *Context) {
}
VaListTagDecl->completeDefinition();
Context->VaListTagDecl = VaListTagDecl;
- QualType VaListTagType = Context->getRecordType(VaListTagDecl);
+ CanQualType VaListTagType = Context->getCanonicalTagType(VaListTagDecl);
// };
@@ -10059,7 +10167,7 @@ CreateAAPCSABIBuiltinVaListDecl(const ASTContext *Context) {
Context->VaListTagDecl = VaListDecl;
// typedef struct __va_list __builtin_va_list;
- QualType T = Context->getRecordType(VaListDecl);
+ CanQualType T = Context->getCanonicalTagType(VaListDecl);
return Context->buildImplicitTypedef(T, "__builtin_va_list");
}
@@ -10106,7 +10214,7 @@ CreateSystemZBuiltinVaListDecl(const ASTContext *Context) {
}
VaListTagDecl->completeDefinition();
Context->VaListTagDecl = VaListTagDecl;
- QualType VaListTagType = Context->getRecordType(VaListTagDecl);
+ CanQualType VaListTagType = Context->getCanonicalTagType(VaListTagDecl);
// };
@@ -10153,13 +10261,15 @@ static TypedefDecl *CreateHexagonBuiltinVaListDecl(const ASTContext *Context) {
}
VaListTagDecl->completeDefinition();
Context->VaListTagDecl = VaListTagDecl;
- QualType VaListTagType = Context->getRecordType(VaListTagDecl);
+ CanQualType VaListTagType = Context->getCanonicalTagType(VaListTagDecl);
// } __va_list_tag;
TypedefDecl *VaListTagTypedefDecl =
Context->buildImplicitTypedef(VaListTagType, "__va_list_tag");
- QualType VaListTagTypedefType = Context->getTypedefType(VaListTagTypedefDecl);
+ QualType VaListTagTypedefType =
+ Context->getTypedefType(ElaboratedTypeKeyword::None,
+ /*Qualifier=*/std::nullopt, VaListTagTypedefDecl);
// typedef __va_list_tag __builtin_va_list[1];
llvm::APInt Size(Context->getTypeSize(Context->getSizeType()), 1);
@@ -10197,7 +10307,7 @@ CreateXtensaABIBuiltinVaListDecl(const ASTContext *Context) {
}
VaListTagDecl->completeDefinition();
Context->VaListTagDecl = VaListTagDecl;
- QualType VaListTagType = Context->getRecordType(VaListTagDecl);
+ CanQualType VaListTagType = Context->getCanonicalTagType(VaListTagDecl);
// } __va_list_tag;
TypedefDecl *VaListTagTypedefDecl =
@@ -10311,7 +10421,7 @@ TemplateName ASTContext::getAssumedTemplateName(DeclarationName Name) const {
/// Retrieve the template name that represents a qualified
/// template name such as \c std::vector.
-TemplateName ASTContext::getQualifiedTemplateName(NestedNameSpecifier *NNS,
+TemplateName ASTContext::getQualifiedTemplateName(NestedNameSpecifier Qualifier,
bool TemplateKeyword,
TemplateName Template) const {
assert(Template.getKind() == TemplateName::Template ||
@@ -10319,14 +10429,14 @@ TemplateName ASTContext::getQualifiedTemplateName(NestedNameSpecifier *NNS,
// FIXME: Canonicalization?
llvm::FoldingSetNodeID ID;
- QualifiedTemplateName::Profile(ID, NNS, TemplateKeyword, Template);
+ QualifiedTemplateName::Profile(ID, Qualifier, TemplateKeyword, Template);
void *InsertPos = nullptr;
QualifiedTemplateName *QTN =
- QualifiedTemplateNames.FindNodeOrInsertPos(ID, InsertPos);
+ QualifiedTemplateNames.FindNodeOrInsertPos(ID, InsertPos);
if (!QTN) {
QTN = new (*this, alignof(QualifiedTemplateName))
- QualifiedTemplateName(NNS, TemplateKeyword, Template);
+ QualifiedTemplateName(Qualifier, TemplateKeyword, Template);
QualifiedTemplateNames.InsertNode(QTN, InsertPos);
}
@@ -11296,7 +11406,7 @@ QualType ASTContext::mergeTransparentUnionType(QualType T, QualType SubType,
bool OfBlockPointer,
bool Unqualified) {
if (const RecordType *UT = T->getAsUnionType()) {
- RecordDecl *UD = UT->getDecl();
+ RecordDecl *UD = UT->getOriginalDecl()->getMostRecentDecl();
if (UD->hasAttr<TransparentUnionAttr>()) {
for (const auto *I : UD->fields()) {
QualType ET = I->getType().getUnqualifiedType();
@@ -11528,7 +11638,8 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
// Look at the converted type of enum types, since that is the type used
// to pass enum values.
if (const auto *Enum = paramTy->getAs<EnumType>()) {
- paramTy = Enum->getDecl()->getIntegerType();
+ paramTy =
+ Enum->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
if (paramTy.isNull())
return {};
}
@@ -11560,7 +11671,8 @@ static QualType mergeEnumWithInteger(ASTContext &Context, const EnumType *ET,
// a signed integer type, or an unsigned integer type.
// Compatibility is based on the underlying type, not the promotion
// type.
- QualType underlyingType = ET->getDecl()->getIntegerType();
+ QualType underlyingType =
+ ET->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
if (underlyingType.isNull())
return {};
if (Context.hasSameType(underlyingType, other))
@@ -12119,7 +12231,7 @@ QualType ASTContext::mergeObjCGCQualifiers(QualType LHS, QualType RHS) {
unsigned ASTContext::getIntWidth(QualType T) const {
if (const auto *ET = T->getAs<EnumType>())
- T = ET->getDecl()->getIntegerType();
+ T = ET->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
if (T->isBooleanType())
return 1;
if (const auto *EIT = T->getAs<BitIntType>())
@@ -12145,7 +12257,7 @@ QualType ASTContext::getCorrespondingUnsignedType(QualType T) const {
// For enums, get the underlying integer type of the enum, and let the general
// integer type signchanging code handle it.
if (const auto *ETy = T->getAs<EnumType>())
- T = ETy->getDecl()->getIntegerType();
+ T = ETy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
switch (T->castAs<BuiltinType>()->getKind()) {
case BuiltinType::Char_U:
@@ -12219,7 +12331,7 @@ QualType ASTContext::getCorrespondingSignedType(QualType T) const {
// For enums, get the underlying integer type of the enum, and let the general
// integer type signchanging code handle it.
if (const auto *ETy = T->getAs<EnumType>())
- T = ETy->getDecl()->getIntegerType();
+ T = ETy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
switch (T->castAs<BuiltinType>()->getKind()) {
case BuiltinType::Char_S:
@@ -13573,7 +13685,7 @@ static T *getCommonDeclChecked(T *X, T *Y) {
const_cast<Decl *>(cast<Decl>(Y))));
}
-static TemplateName getCommonTemplateName(ASTContext &Ctx, TemplateName X,
+static TemplateName getCommonTemplateName(const ASTContext &Ctx, TemplateName X,
TemplateName Y,
bool IgnoreDeduced = false) {
if (X.getAsVoidPointer() == Y.getAsVoidPointer())
@@ -13588,7 +13700,7 @@ static TemplateName getCommonTemplateName(ASTContext &Ctx, TemplateName X,
return CX;
}
-static TemplateName getCommonTemplateNameChecked(ASTContext &Ctx,
+static TemplateName getCommonTemplateNameChecked(const ASTContext &Ctx,
TemplateName X, TemplateName Y,
bool IgnoreDeduced) {
TemplateName R = getCommonTemplateName(Ctx, X, Y, IgnoreDeduced);
@@ -13596,7 +13708,7 @@ static TemplateName getCommonTemplateNameChecked(ASTContext &Ctx,
return R;
}
-static auto getCommonTypes(ASTContext &Ctx, ArrayRef<QualType> Xs,
+static auto getCommonTypes(const ASTContext &Ctx, ArrayRef<QualType> Xs,
ArrayRef<QualType> Ys, bool Unqualified = false) {
assert(Xs.size() == Ys.size());
SmallVector<QualType, 8> Rs(Xs.size());
@@ -13611,7 +13723,7 @@ static SourceLocation getCommonAttrLoc(const T *X, const T *Y) {
: SourceLocation();
}
-static TemplateArgument getCommonTemplateArgument(ASTContext &Ctx,
+static TemplateArgument getCommonTemplateArgument(const ASTContext &Ctx,
const TemplateArgument &X,
const TemplateArgument &Y) {
if (X.getKind() != Y.getKind())
@@ -13657,7 +13769,7 @@ static TemplateArgument getCommonTemplateArgument(ASTContext &Ctx,
}
}
-static bool getCommonTemplateArguments(ASTContext &Ctx,
+static bool getCommonTemplateArguments(const ASTContext &Ctx,
SmallVectorImpl<TemplateArgument> &R,
ArrayRef<TemplateArgument> Xs,
ArrayRef<TemplateArgument> Ys) {
@@ -13672,7 +13784,7 @@ static bool getCommonTemplateArguments(ASTContext &Ctx,
return false;
}
-static auto getCommonTemplateArguments(ASTContext &Ctx,
+static auto getCommonTemplateArguments(const ASTContext &Ctx,
ArrayRef<TemplateArgument> Xs,
ArrayRef<TemplateArgument> Ys) {
SmallVector<TemplateArgument, 8> R;
@@ -13683,163 +13795,101 @@ static auto getCommonTemplateArguments(ASTContext &Ctx,
}
template <class T>
-static ElaboratedTypeKeyword getCommonTypeKeyword(const T *X, const T *Y) {
- return X->getKeyword() == Y->getKeyword() ? X->getKeyword()
- : ElaboratedTypeKeyword::None;
+static ElaboratedTypeKeyword getCommonTypeKeyword(const T *X, const T *Y,
+ bool IsSame) {
+ ElaboratedTypeKeyword KX = X->getKeyword(), KY = Y->getKeyword();
+ if (KX == KY)
+ return KX;
+ KX = getCanonicalElaboratedTypeKeyword(KX);
+ assert(!IsSame || KX == getCanonicalElaboratedTypeKeyword(KY));
+ return KX;
}
/// Returns a NestedNameSpecifier which has only the common sugar
/// present in both NNS1 and NNS2.
-static NestedNameSpecifier *getCommonNNS(ASTContext &Ctx,
- NestedNameSpecifier *NNS1,
- NestedNameSpecifier *NNS2,
- bool IsSame) {
+static NestedNameSpecifier getCommonNNS(const ASTContext &Ctx,
+ NestedNameSpecifier NNS1,
+ NestedNameSpecifier NNS2, bool IsSame) {
// If they are identical, all sugar is common.
if (NNS1 == NNS2)
return NNS1;
- // IsSame implies both NNSes are equivalent.
- NestedNameSpecifier *Canon = Ctx.getCanonicalNestedNameSpecifier(NNS1);
- if (Canon != Ctx.getCanonicalNestedNameSpecifier(NNS2)) {
+ // IsSame implies both Qualifiers are equivalent.
+ NestedNameSpecifier Canon = NNS1.getCanonical();
+ if (Canon != NNS2.getCanonical()) {
assert(!IsSame && "Should be the same NestedNameSpecifier");
// If they are not the same, there is nothing to unify.
- // FIXME: It would be useful here if we could represent a canonically
- // empty NNS, which is not identical to an empty-as-written NNS.
- return nullptr;
+ return std::nullopt;
}
- NestedNameSpecifier *R = nullptr;
- NestedNameSpecifier::SpecifierKind K1 = NNS1->getKind(), K2 = NNS2->getKind();
- switch (K1) {
- case NestedNameSpecifier::SpecifierKind::Identifier: {
- assert(K2 == NestedNameSpecifier::SpecifierKind::Identifier);
- IdentifierInfo *II = NNS1->getAsIdentifier();
- assert(II == NNS2->getAsIdentifier());
- // For an identifier, the prefixes are significant, so they must be the
- // same.
- NestedNameSpecifier *P = ::getCommonNNS(Ctx, NNS1->getPrefix(),
- NNS2->getPrefix(), /*IsSame=*/true);
- R = NestedNameSpecifier::Create(Ctx, P, II);
- break;
- }
- case NestedNameSpecifier::SpecifierKind::Namespace: {
- assert(K2 == NestedNameSpecifier::SpecifierKind::Namespace);
- // The prefixes for namespaces are not significant, its declaration
- // identifies it uniquely.
- NestedNameSpecifier *P =
- ::getCommonNNS(Ctx, NNS1->getPrefix(), NNS2->getPrefix(),
- /*IsSame=*/false);
- NamespaceBaseDecl *Namespace1 = NNS1->getAsNamespace(),
- *Namespace2 = NNS2->getAsNamespace();
+ NestedNameSpecifier R = std::nullopt;
+ NestedNameSpecifier::Kind Kind = NNS1.getKind();
+ assert(Kind == NNS2.getKind());
+ switch (Kind) {
+ case NestedNameSpecifier::Kind::Namespace: {
+ auto [Namespace1, Prefix1] = NNS1.getAsNamespaceAndPrefix();
+ auto [Namespace2, Prefix2] = NNS2.getAsNamespaceAndPrefix();
auto Kind = Namespace1->getKind();
if (Kind != Namespace2->getKind() ||
(Kind == Decl::NamespaceAlias &&
!declaresSameEntity(Namespace1, Namespace2))) {
- R = NestedNameSpecifier::Create(
- Ctx, P,
+ R = NestedNameSpecifier(
+ Ctx,
::getCommonDeclChecked(Namespace1->getNamespace(),
- Namespace2->getNamespace()));
+ Namespace2->getNamespace()),
+ /*Prefix=*/std::nullopt);
break;
}
- R = NestedNameSpecifier::Create(
- Ctx, P, ::getCommonDeclChecked(Namespace1, Namespace2));
+ // The prefixes for namespaces are not significant, its declaration
+ // identifies it uniquely.
+ NestedNameSpecifier Prefix = ::getCommonNNS(Ctx, Prefix1, Prefix2,
+ /*IsSame=*/false);
+ R = NestedNameSpecifier(Ctx, ::getCommonDeclChecked(Namespace1, Namespace2),
+ Prefix);
break;
}
- case NestedNameSpecifier::SpecifierKind::TypeSpec: {
- // FIXME: See comment below, on Super case.
- if (K2 == NestedNameSpecifier::SpecifierKind::Super)
- return Ctx.getCanonicalNestedNameSpecifier(NNS1);
-
- assert(K2 == NestedNameSpecifier::SpecifierKind::TypeSpec);
-
- const Type *T1 = NNS1->getAsType(), *T2 = NNS2->getAsType();
- if (T1 == T2) {
- // If the types are indentical, then only the prefixes differ.
- // A well-formed NNS never has these types, as they have
- // special normalized forms.
- assert((!isa<DependentNameType, ElaboratedType>(T1)));
- // Only for a DependentTemplateSpecializationType the prefix
- // is actually significant. A DependentName, which would be another
- // plausible case, cannot occur here, as explained above.
- bool IsSame = isa<DependentTemplateSpecializationType>(T1);
- NestedNameSpecifier *P =
- ::getCommonNNS(Ctx, NNS1->getPrefix(), NNS2->getPrefix(), IsSame);
- R = NestedNameSpecifier::Create(Ctx, P, T1);
- break;
- }
- // TODO: Try to salvage the original prefix.
- // If getCommonSugaredType removed any top level sugar, the original prefix
- // is not applicable anymore.
+ case NestedNameSpecifier::Kind::Type: {
+ const Type *T1 = NNS1.getAsType(), *T2 = NNS2.getAsType();
const Type *T = Ctx.getCommonSugaredType(QualType(T1, 0), QualType(T2, 0),
/*Unqualified=*/true)
.getTypePtr();
-
- // A NestedNameSpecifier has special normalization rules for certain types.
- switch (T->getTypeClass()) {
- case Type::Elaborated: {
- // An ElaboratedType is stripped off, it's Qualifier becomes the prefix.
- auto *ET = cast<ElaboratedType>(T);
- R = NestedNameSpecifier::Create(Ctx, ET->getQualifier(),
- ET->getNamedType().getTypePtr());
- break;
- }
- case Type::DependentName: {
- // A DependentName is turned into an Identifier NNS.
- auto *DN = cast<DependentNameType>(T);
- R = NestedNameSpecifier::Create(Ctx, DN->getQualifier(),
- DN->getIdentifier());
- break;
- }
- case Type::DependentTemplateSpecialization: {
- // A DependentTemplateSpecializationType loses it's Qualifier, which
- // is turned into the prefix.
- auto *DTST = cast<DependentTemplateSpecializationType>(T);
- const DependentTemplateStorage &DTN = DTST->getDependentTemplateName();
- DependentTemplateStorage NewDTN(/*Qualifier=*/nullptr, DTN.getName(),
- DTN.hasTemplateKeyword());
- T = Ctx.getDependentTemplateSpecializationType(DTST->getKeyword(), NewDTN,
- DTST->template_arguments())
- .getTypePtr();
- R = NestedNameSpecifier::Create(Ctx, DTN.getQualifier(), T);
- break;
- }
- default:
- R = NestedNameSpecifier::Create(Ctx, /*Prefix=*/nullptr, T);
- break;
- }
+ R = NestedNameSpecifier(T);
break;
}
- case NestedNameSpecifier::SpecifierKind::Super:
+ case NestedNameSpecifier::Kind::MicrosoftSuper: {
// FIXME: Can __super even be used with data members?
// If it's only usable in functions, we will never see it here,
// unless we save the qualifiers used in function types.
// In that case, it might be possible NNS2 is a type,
// in which case we should degrade the result to
// a CXXRecordType.
- return Ctx.getCanonicalNestedNameSpecifier(NNS1);
- case NestedNameSpecifier::SpecifierKind::Global:
- // The global NNS is a singleton.
- assert(K2 == NestedNameSpecifier::SpecifierKind::Global &&
- "Global NNS cannot be equivalent to any other kind");
- llvm_unreachable("Global NestedNameSpecifiers did not compare equal");
- }
- assert(Ctx.getCanonicalNestedNameSpecifier(R) == Canon);
+ R = NestedNameSpecifier(getCommonDeclChecked(NNS1.getAsMicrosoftSuper(),
+ NNS2.getAsMicrosoftSuper()));
+ break;
+ }
+ case NestedNameSpecifier::Kind::Null:
+ case NestedNameSpecifier::Kind::Global:
+ // These are singletons.
+ llvm_unreachable("singletons did not compare equal");
+ }
+ assert(R.getCanonical() == Canon);
return R;
}
template <class T>
-static NestedNameSpecifier *getCommonQualifier(ASTContext &Ctx, const T *X,
- const T *Y, bool IsSame) {
+static NestedNameSpecifier getCommonQualifier(const ASTContext &Ctx, const T *X,
+ const T *Y, bool IsSame) {
return ::getCommonNNS(Ctx, X->getQualifier(), Y->getQualifier(), IsSame);
}
template <class T>
-static QualType getCommonElementType(ASTContext &Ctx, const T *X, const T *Y) {
+static QualType getCommonElementType(const ASTContext &Ctx, const T *X,
+ const T *Y) {
return Ctx.getCommonSugaredType(X->getElementType(), Y->getElementType());
}
template <class T>
-static QualType getCommonArrayElementType(ASTContext &Ctx, const T *X,
+static QualType getCommonArrayElementType(const ASTContext &Ctx, const T *X,
Qualifiers &QX, const T *Y,
Qualifiers &QY) {
QualType EX = X->getElementType(), EY = Y->getElementType();
@@ -13856,11 +13906,13 @@ static QualType getCommonArrayElementType(ASTContext &Ctx, const T *X,
}
template <class T>
-static QualType getCommonPointeeType(ASTContext &Ctx, const T *X, const T *Y) {
+static QualType getCommonPointeeType(const ASTContext &Ctx, const T *X,
+ const T *Y) {
return Ctx.getCommonSugaredType(X->getPointeeType(), Y->getPointeeType());
}
-template <class T> static auto *getCommonSizeExpr(ASTContext &Ctx, T *X, T *Y) {
+template <class T>
+static auto *getCommonSizeExpr(const ASTContext &Ctx, T *X, T *Y) {
assert(Ctx.hasSameExpr(X->getSizeExpr(), Y->getSizeExpr()));
return X->getSizeExpr();
}
@@ -13880,8 +13932,9 @@ static auto getCommonIndexTypeCVRQualifiers(const ArrayType *X,
// each type (in a canonical sense) only once, in the order they appear
// from X to Y. If they occur in both X and Y, the result will contain
// the common sugared type between them.
-static void mergeTypeLists(ASTContext &Ctx, SmallVectorImpl<QualType> &Out,
- ArrayRef<QualType> X, ArrayRef<QualType> Y) {
+static void mergeTypeLists(const ASTContext &Ctx,
+ SmallVectorImpl<QualType> &Out, ArrayRef<QualType> X,
+ ArrayRef<QualType> Y) {
llvm::DenseMap<QualType, unsigned> Found;
for (auto Ts : {X, Y}) {
for (QualType T : Ts) {
@@ -13900,7 +13953,7 @@ FunctionProtoType::ExceptionSpecInfo
ASTContext::mergeExceptionSpecs(FunctionProtoType::ExceptionSpecInfo ESI1,
FunctionProtoType::ExceptionSpecInfo ESI2,
SmallVectorImpl<QualType> &ExceptionTypeStorage,
- bool AcceptDependent) {
+ bool AcceptDependent) const {
ExceptionSpecificationType EST1 = ESI1.Type, EST2 = ESI2.Type;
// If either of them can throw anything, that is the result.
@@ -13964,7 +14017,7 @@ ASTContext::mergeExceptionSpecs(FunctionProtoType::ExceptionSpecInfo ESI1,
llvm_unreachable("invalid ExceptionSpecificationType");
}
-static QualType getCommonNonSugarTypeNode(ASTContext &Ctx, const Type *X,
+static QualType getCommonNonSugarTypeNode(const ASTContext &Ctx, const Type *X,
Qualifiers &QX, const Type *Y,
Qualifiers &QY) {
Type::TypeClass TC = X->getTypeClass();
@@ -13982,10 +14035,8 @@ static QualType getCommonNonSugarTypeNode(ASTContext &Ctx, const Type *X,
SUGAR_FREE_TYPE(Builtin)
SUGAR_FREE_TYPE(DeducedTemplateSpecialization)
SUGAR_FREE_TYPE(DependentBitInt)
- SUGAR_FREE_TYPE(Enum)
SUGAR_FREE_TYPE(BitInt)
SUGAR_FREE_TYPE(ObjCInterface)
- SUGAR_FREE_TYPE(Record)
SUGAR_FREE_TYPE(SubstTemplateTypeParmPack)
SUGAR_FREE_TYPE(UnresolvedUsing)
SUGAR_FREE_TYPE(HLSLAttributedResource)
@@ -14203,13 +14254,15 @@ static QualType getCommonNonSugarTypeNode(ASTContext &Ctx, const Type *X,
getCommonElementType(Ctx, VX, VY), getCommonSizeExpr(Ctx, VX, VY),
getCommonAttrLoc(VX, VY), VX->getVectorKind());
}
+ case Type::Enum:
+ case Type::Record:
case Type::InjectedClassName: {
- const auto *IX = cast<InjectedClassNameType>(X),
- *IY = cast<InjectedClassNameType>(Y);
- return Ctx.getInjectedClassNameType(
- getCommonDeclChecked(IX->getDecl(), IY->getDecl()),
- Ctx.getCommonSugaredType(IX->getInjectedSpecializationType(),
- IY->getInjectedSpecializationType()));
+ const auto *TX = cast<TagType>(X), *TY = cast<TagType>(Y);
+ return Ctx.getTagType(
+ ::getCommonTypeKeyword(TX, TY, /*IsSame=*/false),
+ ::getCommonQualifier(Ctx, TX, TY, /*IsSame=*/false),
+ ::getCommonDeclChecked(TX->getOriginalDecl(), TY->getOriginalDecl()),
+ /*OwnedTag=*/false);
}
case Type::TemplateSpecialization: {
const auto *TX = cast<TemplateSpecializationType>(X),
@@ -14217,6 +14270,7 @@ static QualType getCommonNonSugarTypeNode(ASTContext &Ctx, const Type *X,
auto As = getCommonTemplateArguments(Ctx, TX->template_arguments(),
TY->template_arguments());
return Ctx.getTemplateSpecializationType(
+ getCommonTypeKeyword(TX, TY, /*IsSame=*/false),
::getCommonTemplateNameChecked(Ctx, TX->getTemplateName(),
TY->getTemplateName(),
/*IgnoreDeduced=*/true),
@@ -14244,7 +14298,7 @@ static QualType getCommonNonSugarTypeNode(ASTContext &Ctx, const Type *X,
*NY = cast<DependentNameType>(Y);
assert(NX->getIdentifier() == NY->getIdentifier());
return Ctx.getDependentNameType(
- getCommonTypeKeyword(NX, NY),
+ getCommonTypeKeyword(NX, NY, /*IsSame=*/true),
getCommonQualifier(Ctx, NX, NY, /*IsSame=*/true), NX->getIdentifier());
}
case Type::DependentTemplateSpecialization: {
@@ -14260,7 +14314,7 @@ static QualType getCommonNonSugarTypeNode(ASTContext &Ctx, const Type *X,
/*IsSame=*/true),
SX.getName(), SX.hasTemplateKeyword() || SY.hasTemplateKeyword());
return Ctx.getDependentTemplateSpecializationType(
- getCommonTypeKeyword(TX, TY), Name, As);
+ getCommonTypeKeyword(TX, TY, /*IsSame=*/true), Name, As);
}
case Type::UnaryTransform: {
const auto *TX = cast<UnaryTransformType>(X),
@@ -14301,7 +14355,7 @@ static QualType getCommonNonSugarTypeNode(ASTContext &Ctx, const Type *X,
llvm_unreachable("Unknown Type Class");
}
-static QualType getCommonSugarTypeNode(ASTContext &Ctx, const Type *X,
+static QualType getCommonSugarTypeNode(const ASTContext &Ctx, const Type *X,
const Type *Y,
SplitQualType Underlying) {
Type::TypeClass TC = X->getTypeClass();
@@ -14413,15 +14467,6 @@ static QualType getCommonSugarTypeNode(ASTContext &Ctx, const Type *X,
case Type::DeducedTemplateSpecialization:
// FIXME: Try to merge these.
return QualType();
-
- case Type::Elaborated: {
- const auto *EX = cast<ElaboratedType>(X), *EY = cast<ElaboratedType>(Y);
- return Ctx.getElaboratedType(
- ::getCommonTypeKeyword(EX, EY),
- ::getCommonQualifier(Ctx, EX, EY, /*IsSame=*/false),
- Ctx.getQualifiedType(Underlying),
- ::getCommonDecl(EX->getOwnedTagDecl(), EY->getOwnedTagDecl()));
- }
case Type::MacroQualified: {
const auto *MX = cast<MacroQualifiedType>(X),
*MY = cast<MacroQualifiedType>(Y);
@@ -14465,16 +14510,19 @@ static QualType getCommonSugarTypeNode(ASTContext &Ctx, const Type *X,
if (getCommonTemplateArguments(Ctx, As, TX->template_arguments(),
TY->template_arguments()))
return QualType();
- return Ctx.getTemplateSpecializationType(CTN, As,
- /*CanonicalArgs=*/{},
- Ctx.getQualifiedType(Underlying));
+ return Ctx.getTemplateSpecializationType(
+ getCommonTypeKeyword(TX, TY, /*IsSame=*/false), CTN, As,
+ /*CanonicalArgs=*/{}, Ctx.getQualifiedType(Underlying));
}
case Type::Typedef: {
const auto *TX = cast<TypedefType>(X), *TY = cast<TypedefType>(Y);
const TypedefNameDecl *CD = ::getCommonDecl(TX->getDecl(), TY->getDecl());
if (!CD)
return QualType();
- return Ctx.getTypedefType(CD, Ctx.getQualifiedType(Underlying));
+ return Ctx.getTypedefType(
+ ::getCommonTypeKeyword(TX, TY, /*IsSame=*/false),
+ ::getCommonQualifier(Ctx, TX, TY, /*IsSame=*/false), CD,
+ Ctx.getQualifiedType(Underlying));
}
case Type::TypeOf: {
// The common sugar between two typeof expressions, where one is
@@ -14505,11 +14553,12 @@ static QualType getCommonSugarTypeNode(ASTContext &Ctx, const Type *X,
}
case Type::Using: {
const auto *UX = cast<UsingType>(X), *UY = cast<UsingType>(Y);
- const UsingShadowDecl *CD =
- ::getCommonDecl(UX->getFoundDecl(), UY->getFoundDecl());
+ const UsingShadowDecl *CD = ::getCommonDecl(UX->getDecl(), UY->getDecl());
if (!CD)
return QualType();
- return Ctx.getUsingType(CD, Ctx.getQualifiedType(Underlying));
+ return Ctx.getUsingType(::getCommonTypeKeyword(UX, UY, /*IsSame=*/false),
+ ::getCommonQualifier(Ctx, UX, UY, /*IsSame=*/false),
+ CD, Ctx.getQualifiedType(Underlying));
}
case Type::MemberPointer: {
const auto *PX = cast<MemberPointerType>(X),
@@ -14568,7 +14617,7 @@ static auto unwrapSugar(SplitQualType &T, Qualifiers &QTotal) {
}
QualType ASTContext::getCommonSugaredType(QualType X, QualType Y,
- bool Unqualified) {
+ bool Unqualified) const {
assert(Unqualified ? hasSameUnqualifiedType(X, Y) : hasSameType(X, Y));
if (X == Y)
return X;
diff --git a/clang/lib/AST/ASTDiagnostic.cpp b/clang/lib/AST/ASTDiagnostic.cpp
index 2ef0c31..d7fd411 100644
--- a/clang/lib/AST/ASTDiagnostic.cpp
+++ b/clang/lib/AST/ASTDiagnostic.cpp
@@ -36,11 +36,6 @@ QualType clang::desugarForDiagnostic(ASTContext &Context, QualType QT,
while (true) {
const Type *Ty = QC.strip(QT);
- // Don't aka just because we saw an elaborated type...
- if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(Ty)) {
- QT = ET->desugar();
- continue;
- }
// ... or a using type ...
if (const UsingType *UT = dyn_cast<UsingType>(Ty)) {
QT = UT->desugar();
@@ -130,7 +125,8 @@ QualType clang::desugarForDiagnostic(ASTContext &Context, QualType QT,
if (DesugarArgument) {
ShouldAKA = true;
QT = Context.getTemplateSpecializationType(
- TST->getTemplateName(), Args, /*CanonicalArgs=*/{}, QT);
+ TST->getKeyword(), TST->getTemplateName(), Args,
+ /*CanonicalArgs=*/{}, QT);
}
break;
}
@@ -200,7 +196,8 @@ break; \
// Don't desugar through the primary typedef of an anonymous type.
if (const TagType *UTT = Underlying->getAs<TagType>())
if (const TypedefType *QTT = dyn_cast<TypedefType>(QT))
- if (UTT->getDecl()->getTypedefNameForAnonDecl() == QTT->getDecl())
+ if (UTT->getOriginalDecl()->getTypedefNameForAnonDecl() ==
+ QTT->getDecl())
break;
// Record that we actually looked through an opaque type here.
@@ -461,13 +458,12 @@ void clang::FormatASTNodeDiagnosticArgument(
ND->getNameForDiagnostic(OS, Context.getPrintingPolicy(), Qualified);
break;
}
- case DiagnosticsEngine::ak_nestednamespec: {
- NestedNameSpecifier *NNS = reinterpret_cast<NestedNameSpecifier*>(Val);
- NNS->print(OS, Context.getPrintingPolicy(),
+ case DiagnosticsEngine::ak_nestednamespec:
+ NestedNameSpecifier::getFromVoidPointer(reinterpret_cast<void *>(Val))
+ .print(OS, Context.getPrintingPolicy(),
/*ResolveTemplateArguments=*/false,
/*PrintFinalScopeResOp=*/false);
break;
- }
case DiagnosticsEngine::ak_declcontext: {
DeclContext *DC = reinterpret_cast<DeclContext *> (Val);
assert(DC && "Should never have a null declaration context");
@@ -484,9 +480,8 @@ void clang::FormatASTNodeDiagnosticArgument(
} else if (isLambdaCallOperator(DC)) {
OS << "lambda expression";
} else if (TypeDecl *Type = dyn_cast<TypeDecl>(DC)) {
- OS << ConvertTypeToDiagnosticString(Context,
- Context.getTypeDeclType(Type),
- PrevArgs, QualTypeVals);
+ OS << ConvertTypeToDiagnosticString(
+ Context, Context.getTypeDeclType(Type), PrevArgs, QualTypeVals);
} else {
assert(isa<NamedDecl>(DC) && "Expected a NamedDecl");
NamedDecl *ND = cast<NamedDecl>(DC);
@@ -1158,12 +1153,13 @@ class TemplateDiff {
return nullptr;
const ClassTemplateSpecializationDecl *CTSD =
- dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());
+ dyn_cast<ClassTemplateSpecializationDecl>(RT->getOriginalDecl());
if (!CTSD)
return nullptr;
Ty = Context.getTemplateSpecializationType(
+ ElaboratedTypeKeyword::None,
TemplateName(CTSD->getSpecializedTemplate()),
CTSD->getTemplateArgs().asArray(), /*CanonicalArgs=*/{},
Ty.getLocalUnqualifiedType().getCanonicalType());
@@ -1743,25 +1739,10 @@ class TemplateDiff {
std::string FromTypeStr = FromType.isNull() ? "(no argument)"
: FromType.getAsString(Policy);
- std::string ToTypeStr = ToType.isNull() ? "(no argument)"
- : ToType.getAsString(Policy);
- // Print without ElaboratedType sugar if it is better.
+ std::string ToTypeStr =
+ ToType.isNull() ? "(no argument)" : ToType.getAsString(Policy);
// TODO: merge this with other aka printing above.
if (FromTypeStr == ToTypeStr) {
- const auto *FromElTy = dyn_cast<ElaboratedType>(FromType),
- *ToElTy = dyn_cast<ElaboratedType>(ToType);
- if (FromElTy || ToElTy) {
- std::string FromNamedTypeStr =
- FromElTy ? FromElTy->getNamedType().getAsString(Policy)
- : FromTypeStr;
- std::string ToNamedTypeStr =
- ToElTy ? ToElTy->getNamedType().getAsString(Policy) : ToTypeStr;
- if (FromNamedTypeStr != ToNamedTypeStr) {
- FromTypeStr = FromNamedTypeStr;
- ToTypeStr = ToNamedTypeStr;
- goto PrintTypes;
- }
- }
// Switch to canonical typename if it is better.
std::string FromCanTypeStr =
FromType.getCanonicalType().getAsString(Policy);
@@ -1772,8 +1753,8 @@ class TemplateDiff {
}
}
- PrintTypes:
- if (PrintTree) OS << '[';
+ if (PrintTree)
+ OS << '[';
OS << (FromDefault ? "(default) " : "");
Bold();
OS << FromTypeStr;
diff --git a/clang/lib/AST/ASTDumper.cpp b/clang/lib/AST/ASTDumper.cpp
index 5e4487e..8e651a0 100644
--- a/clang/lib/AST/ASTDumper.cpp
+++ b/clang/lib/AST/ASTDumper.cpp
@@ -117,7 +117,9 @@ void ASTDumper::dumpTemplateDeclSpecialization(const SpecializationDecl *D,
// FIXME: The redecls() range sometimes has elements of a less-specific
// type. (In particular, ClassTemplateSpecializationDecl::redecls() gives
// us TagDecls, and should give CXXRecordDecls).
- auto *Redecl = cast<SpecializationDecl>(RedeclWithBadType);
+ auto *Redecl = dyn_cast<SpecializationDecl>(RedeclWithBadType);
+ if (!Redecl)
+ continue;
switch (Redecl->getTemplateSpecializationKind()) {
case TSK_ExplicitInstantiationDeclaration:
case TSK_ExplicitInstantiationDefinition:
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 8e2927b..315ead9 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -949,8 +949,10 @@ ASTNodeImporter::import(const TemplateArgumentLoc &TALoc) {
else
return TSIOrErr.takeError();
} else {
- auto ToTemplateQualifierLocOrErr =
- import(FromInfo.getTemplateQualifierLoc());
+ auto ToTemplateKWLocOrErr = import(FromInfo.getTemplateKwLoc());
+ if (!ToTemplateKWLocOrErr)
+ return ToTemplateKWLocOrErr.takeError();
+ auto ToTemplateQualifierLocOrErr = import(TALoc.getTemplateQualifierLoc());
if (!ToTemplateQualifierLocOrErr)
return ToTemplateQualifierLocOrErr.takeError();
auto ToTemplateNameLocOrErr = import(FromInfo.getTemplateNameLoc());
@@ -961,8 +963,9 @@ ASTNodeImporter::import(const TemplateArgumentLoc &TALoc) {
if (!ToTemplateEllipsisLocOrErr)
return ToTemplateEllipsisLocOrErr.takeError();
ToInfo = TemplateArgumentLocInfo(
- Importer.getToContext(), *ToTemplateQualifierLocOrErr,
- *ToTemplateNameLocOrErr, *ToTemplateEllipsisLocOrErr);
+ Importer.getToContext(), *ToTemplateKWLocOrErr,
+ *ToTemplateQualifierLocOrErr, *ToTemplateNameLocOrErr,
+ *ToTemplateEllipsisLocOrErr);
}
return TemplateArgumentLoc(Arg, ToInfo);
@@ -1597,13 +1600,15 @@ ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) {
ExpectedType ASTNodeImporter::VisitUnresolvedUsingType(
const UnresolvedUsingType *T) {
Error Err = Error::success();
- auto ToD = importChecked(Err, T->getDecl());
- auto ToPrevD = importChecked(Err, T->getDecl()->getPreviousDecl());
+ auto ToQualifier = importChecked(Err, T->getQualifier());
+ auto *ToD = importChecked(Err, T->getDecl());
if (Err)
return std::move(Err);
- return Importer.getToContext().getTypeDeclType(
- ToD, cast_or_null<TypeDecl>(ToPrevD));
+ if (T->isCanonicalUnqualified())
+ return Importer.getToContext().getCanonicalUnresolvedUsingType(ToD);
+ return Importer.getToContext().getUnresolvedUsingType(T->getKeyword(),
+ ToQualifier, ToD);
}
ExpectedType ASTNodeImporter::VisitParenType(const ParenType *T) {
@@ -1631,15 +1636,17 @@ ExpectedType ASTNodeImporter::VisitTypedefType(const TypedefType *T) {
if (!ToDeclOrErr)
return ToDeclOrErr.takeError();
- TypedefNameDecl *ToDecl = *ToDeclOrErr;
- if (ToDecl->getTypeForDecl())
- return QualType(ToDecl->getTypeForDecl(), 0);
+ auto ToQualifierOrErr = import(T->getQualifier());
+ if (!ToQualifierOrErr)
+ return ToQualifierOrErr.takeError();
- ExpectedType ToUnderlyingTypeOrErr = import(T->desugar());
+ ExpectedType ToUnderlyingTypeOrErr =
+ T->typeMatchesDecl() ? QualType() : import(T->desugar());
if (!ToUnderlyingTypeOrErr)
return ToUnderlyingTypeOrErr.takeError();
- return Importer.getToContext().getTypedefType(ToDecl, *ToUnderlyingTypeOrErr);
+ return Importer.getToContext().getTypedefType(
+ T->getKeyword(), *ToQualifierOrErr, *ToDeclOrErr, *ToUnderlyingTypeOrErr);
}
ExpectedType ASTNodeImporter::VisitTypeOfExprType(const TypeOfExprType *T) {
@@ -1658,14 +1665,14 @@ ExpectedType ASTNodeImporter::VisitTypeOfType(const TypeOfType *T) {
}
ExpectedType ASTNodeImporter::VisitUsingType(const UsingType *T) {
- Expected<UsingShadowDecl *> FoundOrErr = import(T->getFoundDecl());
- if (!FoundOrErr)
- return FoundOrErr.takeError();
- Expected<QualType> UnderlyingOrErr = import(T->getUnderlyingType());
- if (!UnderlyingOrErr)
- return UnderlyingOrErr.takeError();
-
- return Importer.getToContext().getUsingType(*FoundOrErr, *UnderlyingOrErr);
+ Error Err = Error::success();
+ auto ToQualifier = importChecked(Err, T->getQualifier());
+ auto *ToD = importChecked(Err, T->getDecl());
+ QualType ToT = importChecked(Err, T->desugar());
+ if (Err)
+ return std::move(Err);
+ return Importer.getToContext().getUsingType(T->getKeyword(), ToQualifier, ToD,
+ ToT);
}
ExpectedType ASTNodeImporter::VisitDecltypeType(const DecltypeType *T) {
@@ -1728,36 +1735,37 @@ ExpectedType ASTNodeImporter::VisitDeducedTemplateSpecializationType(
return ToDeducedTypeOrErr.takeError();
return Importer.getToContext().getDeducedTemplateSpecializationType(
- *ToTemplateNameOrErr, *ToDeducedTypeOrErr, T->isDependentType());
+ T->getKeyword(), *ToTemplateNameOrErr, *ToDeducedTypeOrErr,
+ T->isDependentType());
}
-ExpectedType ASTNodeImporter::VisitInjectedClassNameType(
- const InjectedClassNameType *T) {
- Expected<CXXRecordDecl *> ToDeclOrErr = import(T->getDecl());
+ExpectedType ASTNodeImporter::VisitTagType(const TagType *T) {
+ Expected<TagDecl *> ToDeclOrErr = import(T->getOriginalDecl());
if (!ToDeclOrErr)
return ToDeclOrErr.takeError();
- // The InjectedClassNameType is created in VisitRecordDecl when the
- // T->getDecl() is imported. Here we can return the existing type.
- const Type *Ty = (*ToDeclOrErr)->getTypeForDecl();
- assert(isa_and_nonnull<InjectedClassNameType>(Ty));
- return QualType(Ty, 0);
-}
+ if (T->isCanonicalUnqualified())
+ return Importer.getToContext().getCanonicalTagType(*ToDeclOrErr);
-ExpectedType ASTNodeImporter::VisitRecordType(const RecordType *T) {
- Expected<RecordDecl *> ToDeclOrErr = import(T->getDecl());
- if (!ToDeclOrErr)
- return ToDeclOrErr.takeError();
+ auto ToQualifierOrErr = import(T->getQualifier());
+ if (!ToQualifierOrErr)
+ return ToQualifierOrErr.takeError();
- return Importer.getToContext().getTagDeclType(*ToDeclOrErr);
+ return Importer.getToContext().getTagType(T->getKeyword(), *ToQualifierOrErr,
+ *ToDeclOrErr, T->isTagOwned());
}
ExpectedType ASTNodeImporter::VisitEnumType(const EnumType *T) {
- Expected<EnumDecl *> ToDeclOrErr = import(T->getDecl());
- if (!ToDeclOrErr)
- return ToDeclOrErr.takeError();
+ return VisitTagType(T);
+}
+
+ExpectedType ASTNodeImporter::VisitRecordType(const RecordType *T) {
+ return VisitTagType(T);
+}
- return Importer.getToContext().getTagDeclType(*ToDeclOrErr);
+ExpectedType
+ASTNodeImporter::VisitInjectedClassNameType(const InjectedClassNameType *T) {
+ return VisitTagType(T);
}
ExpectedType ASTNodeImporter::VisitAttributedType(const AttributedType *T) {
@@ -1850,27 +1858,8 @@ ExpectedType ASTNodeImporter::VisitTemplateSpecializationType(
if (!ToUnderlyingOrErr)
return ToUnderlyingOrErr.takeError();
return Importer.getToContext().getTemplateSpecializationType(
- *ToTemplateOrErr, ToTemplateArgs, {}, *ToUnderlyingOrErr);
-}
-
-ExpectedType ASTNodeImporter::VisitElaboratedType(const ElaboratedType *T) {
- // Note: the qualifier in an ElaboratedType is optional.
- auto ToQualifierOrErr = import(T->getQualifier());
- if (!ToQualifierOrErr)
- return ToQualifierOrErr.takeError();
-
- ExpectedType ToNamedTypeOrErr = import(T->getNamedType());
- if (!ToNamedTypeOrErr)
- return ToNamedTypeOrErr.takeError();
-
- Expected<TagDecl *> ToOwnedTagDeclOrErr = import(T->getOwnedTagDecl());
- if (!ToOwnedTagDeclOrErr)
- return ToOwnedTagDeclOrErr.takeError();
-
- return Importer.getToContext().getElaboratedType(T->getKeyword(),
- *ToQualifierOrErr,
- *ToNamedTypeOrErr,
- *ToOwnedTagDeclOrErr);
+ T->getKeyword(), *ToTemplateOrErr, ToTemplateArgs, {},
+ *ToUnderlyingOrErr);
}
ExpectedType
@@ -2168,7 +2157,7 @@ Error ASTNodeImporter::ImportDeclParts(
const Type *LeafT =
getLeafPointeeType(P->getType().getCanonicalType().getTypePtr());
auto *RT = dyn_cast<RecordType>(LeafT);
- if (RT && RT->getDecl() == D) {
+ if (RT && RT->getOriginalDecl() == D) {
Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node)
<< D->getDeclKindName();
return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct);
@@ -2421,8 +2410,8 @@ Error ASTNodeImporter::ImportFieldDeclDefinition(const FieldDecl *From,
const RecordType *RecordTo = ToType->getAs<RecordType>();
if (RecordFrom && RecordTo) {
- FromRecordDecl = RecordFrom->getDecl();
- ToRecordDecl = RecordTo->getDecl();
+ FromRecordDecl = RecordFrom->getOriginalDecl();
+ ToRecordDecl = RecordTo->getOriginalDecl();
}
}
@@ -2643,7 +2632,7 @@ Error ASTNodeImporter::ImportDefinition(
return Err;
ExpectedType ToTypeOrErr =
- import(Importer.getFromContext().getTypeDeclType(From));
+ import(QualType(Importer.getFromContext().getCanonicalTagType(From)));
if (!ToTypeOrErr)
return ToTypeOrErr.takeError();
@@ -3218,7 +3207,7 @@ ExpectedDecl ASTNodeImporter::VisitEnumDecl(EnumDecl *D) {
if (auto *Typedef = dyn_cast<TypedefNameDecl>(FoundDecl)) {
if (const auto *Tag = Typedef->getUnderlyingType()->getAs<TagType>())
- FoundDecl = Tag->getDecl();
+ FoundDecl = Tag->getOriginalDecl();
}
if (auto *FoundEnum = dyn_cast<EnumDecl>(FoundDecl)) {
@@ -3349,7 +3338,7 @@ ExpectedDecl ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
Decl *Found = FoundDecl;
if (auto *Typedef = dyn_cast<TypedefNameDecl>(Found)) {
if (const auto *Tag = Typedef->getUnderlyingType()->getAs<TagType>())
- Found = Tag->getDecl();
+ Found = Tag->getOriginalDecl();
}
if (auto *FoundRecord = dyn_cast<RecordDecl>(Found)) {
@@ -3428,17 +3417,6 @@ ExpectedDecl ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
return CDeclOrErr.takeError();
Numbering.ContextDecl = *CDeclOrErr;
D2CXX->setLambdaNumbering(Numbering);
- } else if (DCXX->isInjectedClassName()) {
- // We have to be careful to do a similar dance to the one in
- // Sema::ActOnStartCXXMemberDeclarations
- const bool DelayTypeCreation = true;
- if (GetImportedOrCreateDecl(
- D2CXX, D, Importer.getToContext(), D->getTagKind(), DC,
- *BeginLocOrErr, Loc, Name.getAsIdentifierInfo(),
- cast_or_null<CXXRecordDecl>(PrevDecl), DelayTypeCreation))
- return D2CXX;
- Importer.getToContext().getTypeDeclType(
- D2CXX, dyn_cast<CXXRecordDecl>(DC));
} else {
if (GetImportedOrCreateDecl(D2CXX, D, Importer.getToContext(),
D->getTagKind(), DC, *BeginLocOrErr, Loc,
@@ -3458,51 +3436,6 @@ ExpectedDecl ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
if (Error Err = importInto(ToDescribed, FromDescribed))
return std::move(Err);
D2CXX->setDescribedClassTemplate(ToDescribed);
- if (!DCXX->isInjectedClassName() && !IsFriendTemplate) {
- // In a record describing a template the type should be an
- // InjectedClassNameType (see Sema::CheckClassTemplate). Update the
- // previously set type to the correct value here (ToDescribed is not
- // available at record create).
- CXXRecordDecl *Injected = nullptr;
- for (NamedDecl *Found : D2CXX->noload_lookup(Name)) {
- auto *Record = dyn_cast<CXXRecordDecl>(Found);
- if (Record && Record->isInjectedClassName()) {
- Injected = Record;
- break;
- }
- }
- // Create an injected type for the whole redecl chain.
- // The chain may contain an already existing injected type at the start,
- // if yes this should be reused. We must ensure that only one type
- // object exists for the injected type (including the injected record
- // declaration), ASTContext does not check it.
- SmallVector<Decl *, 2> Redecls =
- getCanonicalForwardRedeclChain(D2CXX);
- const Type *FrontTy =
- cast<CXXRecordDecl>(Redecls.front())->getTypeForDecl();
- QualType InjSpec;
- if (auto *InjTy = FrontTy->getAs<InjectedClassNameType>())
- InjSpec = InjTy->getInjectedSpecializationType();
- else
- InjSpec = ToDescribed->getInjectedClassNameSpecialization();
- for (auto *R : Redecls) {
- auto *RI = cast<CXXRecordDecl>(R);
- if (R != Redecls.front() ||
- !isa<InjectedClassNameType>(RI->getTypeForDecl()))
- RI->setTypeForDecl(nullptr);
- // This function tries to get the injected type from getTypeForDecl,
- // then from the previous declaration if possible. If not, it creates
- // a new type.
- Importer.getToContext().getInjectedClassNameType(RI, InjSpec);
- }
- // Set the new type for the injected decl too.
- if (Injected) {
- Injected->setTypeForDecl(nullptr);
- // This function will copy the injected type from D2CXX into Injected.
- // The injected decl does not have a previous decl to copy from.
- Importer.getToContext().getTypeDeclType(Injected, D2CXX);
- }
- }
} else if (MemberSpecializationInfo *MemberInfo =
DCXX->getMemberSpecializationInfo()) {
TemplateSpecializationKind SK =
@@ -3826,11 +3759,12 @@ public:
}
std::optional<bool> VisitTagType(const TagType *T) {
- if (auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(T->getDecl()))
+ if (auto *Spec =
+ dyn_cast<ClassTemplateSpecializationDecl>(T->getOriginalDecl()))
for (const auto &Arg : Spec->getTemplateArgs().asArray())
if (checkTemplateArgument(Arg))
return true;
- return isAncestorDeclContextOf(ParentDC, T->getDecl());
+ return isAncestorDeclContextOf(ParentDC, T->getOriginalDecl());
}
std::optional<bool> VisitPointerType(const PointerType *T) {
@@ -3842,17 +3776,11 @@ public:
}
std::optional<bool> VisitTypedefType(const TypedefType *T) {
- const TypedefNameDecl *TD = T->getDecl();
- assert(TD);
- return isAncestorDeclContextOf(ParentDC, TD);
+ return isAncestorDeclContextOf(ParentDC, T->getDecl());
}
std::optional<bool> VisitUsingType(const UsingType *T) {
- if (T->getFoundDecl() &&
- isAncestorDeclContextOf(ParentDC, T->getFoundDecl()))
- return true;
-
- return {};
+ return isAncestorDeclContextOf(ParentDC, T->getDecl());
}
std::optional<bool>
@@ -6521,16 +6449,10 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl(
// Create the specialization.
ClassTemplateSpecializationDecl *D2 = nullptr;
if (PartialSpec) {
- QualType CanonInjType;
- if (Error Err = importInto(
- CanonInjType, PartialSpec->getInjectedSpecializationType()))
- return std::move(Err);
- CanonInjType = CanonInjType.getCanonicalType();
-
if (GetImportedOrCreateDecl<ClassTemplatePartialSpecializationDecl>(
D2, D, Importer.getToContext(), D->getTagKind(), DC, *BeginLocOrErr,
*IdLocOrErr, ToTPList, ClassTemplate, ArrayRef(TemplateArgs),
- CanonInjType,
+ /*CanonInjectedTST=*/CanQualType(),
cast_or_null<ClassTemplatePartialSpecializationDecl>(PrevDecl)))
return D2;
@@ -10050,46 +9972,34 @@ Expected<Stmt *> ASTImporter::Import(Stmt *FromS) {
return ToSOrErr;
}
-Expected<NestedNameSpecifier *>
-ASTImporter::Import(NestedNameSpecifier *FromNNS) {
- if (!FromNNS)
- return nullptr;
-
- NestedNameSpecifier *Prefix = nullptr;
- if (Error Err = importInto(Prefix, FromNNS->getPrefix()))
- return std::move(Err);
-
- switch (FromNNS->getKind()) {
- case NestedNameSpecifier::Identifier:
- assert(FromNNS->getAsIdentifier() && "NNS should contain identifier.");
- return NestedNameSpecifier::Create(ToContext, Prefix,
- Import(FromNNS->getAsIdentifier()));
-
- case NestedNameSpecifier::Namespace:
- if (ExpectedDecl NSOrErr = Import(FromNNS->getAsNamespace())) {
- return NestedNameSpecifier::Create(ToContext, Prefix,
- cast<NamespaceBaseDecl>(*NSOrErr));
- } else
+Expected<NestedNameSpecifier> ASTImporter::Import(NestedNameSpecifier FromNNS) {
+ switch (FromNNS.getKind()) {
+ case NestedNameSpecifier::Kind::Null:
+ case NestedNameSpecifier::Kind::Global:
+ return FromNNS;
+ case NestedNameSpecifier::Kind::Namespace: {
+ auto [Namespace, Prefix] = FromNNS.getAsNamespaceAndPrefix();
+ auto NSOrErr = Import(Namespace);
+ if (!NSOrErr)
return NSOrErr.takeError();
-
- case NestedNameSpecifier::Global:
- return NestedNameSpecifier::GlobalSpecifier(ToContext);
-
- case NestedNameSpecifier::Super:
- if (ExpectedDecl RDOrErr = Import(FromNNS->getAsRecordDecl()))
- return NestedNameSpecifier::SuperSpecifier(ToContext,
- cast<CXXRecordDecl>(*RDOrErr));
+ auto PrefixOrErr = Import(Prefix);
+ if (!PrefixOrErr)
+ return PrefixOrErr.takeError();
+ return NestedNameSpecifier(ToContext, cast<NamespaceBaseDecl>(*NSOrErr),
+ *PrefixOrErr);
+ }
+ case NestedNameSpecifier::Kind::MicrosoftSuper:
+ if (ExpectedDecl RDOrErr = Import(FromNNS.getAsMicrosoftSuper()))
+ return NestedNameSpecifier(cast<CXXRecordDecl>(*RDOrErr));
else
return RDOrErr.takeError();
-
- case NestedNameSpecifier::TypeSpec:
- if (ExpectedTypePtr TyOrErr = Import(FromNNS->getAsType())) {
- return NestedNameSpecifier::Create(ToContext, Prefix, *TyOrErr);
+ case NestedNameSpecifier::Kind::Type:
+ if (ExpectedTypePtr TyOrErr = Import(FromNNS.getAsType())) {
+ return NestedNameSpecifier(*TyOrErr);
} else {
return TyOrErr.takeError();
}
}
-
llvm_unreachable("Invalid nested name specifier kind");
}
@@ -10103,64 +10013,62 @@ ASTImporter::Import(NestedNameSpecifierLoc FromNNS) {
// serialization in reverse order.
while (NNS) {
NestedNames.push_back(NNS);
- NNS = NNS.getPrefix();
+ NNS = NNS.getAsNamespaceAndPrefix().Prefix;
}
NestedNameSpecifierLocBuilder Builder;
while (!NestedNames.empty()) {
NNS = NestedNames.pop_back_val();
- NestedNameSpecifier *Spec = nullptr;
+ NestedNameSpecifier Spec = std::nullopt;
if (Error Err = importInto(Spec, NNS.getNestedNameSpecifier()))
return std::move(Err);
- NestedNameSpecifier::SpecifierKind Kind = Spec->getKind();
+ NestedNameSpecifier::Kind Kind = Spec.getKind();
SourceLocation ToLocalBeginLoc, ToLocalEndLoc;
- if (Kind != NestedNameSpecifier::Super) {
+ if (Kind != NestedNameSpecifier::Kind::MicrosoftSuper) {
if (Error Err = importInto(ToLocalBeginLoc, NNS.getLocalBeginLoc()))
return std::move(Err);
- if (Kind != NestedNameSpecifier::Global)
+ if (Kind != NestedNameSpecifier::Kind::Global)
if (Error Err = importInto(ToLocalEndLoc, NNS.getLocalEndLoc()))
return std::move(Err);
}
switch (Kind) {
- case NestedNameSpecifier::Identifier:
- Builder.Extend(getToContext(), Spec->getAsIdentifier(), ToLocalBeginLoc,
- ToLocalEndLoc);
- break;
-
- case NestedNameSpecifier::Namespace:
- Builder.Extend(getToContext(), Spec->getAsNamespace(), ToLocalBeginLoc,
- ToLocalEndLoc);
+ case NestedNameSpecifier::Kind::Namespace:
+ Builder.Extend(getToContext(), Spec.getAsNamespaceAndPrefix().Namespace,
+ ToLocalBeginLoc, ToLocalEndLoc);
break;
- case NestedNameSpecifier::TypeSpec: {
+ case NestedNameSpecifier::Kind::Type: {
SourceLocation ToTLoc;
- if (Error Err = importInto(ToTLoc, NNS.getTypeLoc().getBeginLoc()))
+ if (Error Err = importInto(ToTLoc, NNS.castAsTypeLoc().getBeginLoc()))
return std::move(Err);
TypeSourceInfo *TSI = getToContext().getTrivialTypeSourceInfo(
- QualType(Spec->getAsType(), 0), ToTLoc);
- Builder.Extend(getToContext(), TSI->getTypeLoc(), ToLocalEndLoc);
+ QualType(Spec.getAsType(), 0), ToTLoc);
+ Builder.Make(getToContext(), TSI->getTypeLoc(), ToLocalEndLoc);
break;
}
- case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Kind::Global:
Builder.MakeGlobal(getToContext(), ToLocalBeginLoc);
break;
- case NestedNameSpecifier::Super: {
+ case NestedNameSpecifier::Kind::MicrosoftSuper: {
auto ToSourceRangeOrErr = Import(NNS.getSourceRange());
if (!ToSourceRangeOrErr)
return ToSourceRangeOrErr.takeError();
- Builder.MakeSuper(getToContext(), Spec->getAsRecordDecl(),
- ToSourceRangeOrErr->getBegin(),
- ToSourceRangeOrErr->getEnd());
+ Builder.MakeMicrosoftSuper(getToContext(), Spec.getAsMicrosoftSuper(),
+ ToSourceRangeOrErr->getBegin(),
+ ToSourceRangeOrErr->getEnd());
+ break;
+ }
+ case NestedNameSpecifier::Kind::Null:
+ llvm_unreachable("unexpected null nested name specifier");
}
- }
}
return Builder.getWithLocInContext(getToContext());
@@ -10740,7 +10648,7 @@ ASTNodeImporter::ImportAPValue(const APValue &FromValue) {
if (Err)
return std::move(Err);
if (auto *RD = dyn_cast<CXXRecordDecl>(FromDecl))
- FromElemTy = Importer.FromContext.getRecordType(RD);
+ FromElemTy = Importer.FromContext.getCanonicalTagType(RD);
else
FromElemTy = cast<ValueDecl>(FromDecl)->getType();
ToPath[LoopIdx] = APValue::LValuePathEntry(APValue::BaseOrMemberType(
diff --git a/clang/lib/AST/ASTImporterLookupTable.cpp b/clang/lib/AST/ASTImporterLookupTable.cpp
index 4ed3198..29c3af1 100644
--- a/clang/lib/AST/ASTImporterLookupTable.cpp
+++ b/clang/lib/AST/ASTImporterLookupTable.cpp
@@ -49,8 +49,6 @@ struct Builder : RecursiveASTVisitor<Builder> {
bool VisitFriendDecl(FriendDecl *D) {
if (D->getFriendType()) {
QualType Ty = D->getFriendType()->getType();
- if (isa<ElaboratedType>(Ty))
- Ty = cast<ElaboratedType>(Ty)->getNamedType();
// A FriendDecl with a dependent type (e.g. ClassTemplateSpecialization)
// always has that decl as child node.
// However, there are non-dependent cases which does not have the
@@ -64,13 +62,15 @@ struct Builder : RecursiveASTVisitor<Builder> {
dyn_cast<SubstTemplateTypeParmType>(Ty)) {
if (SubstTy->getAsCXXRecordDecl())
LT.add(SubstTy->getAsCXXRecordDecl());
- } else if (isa<TypedefType>(Ty)) {
- // We do not put friend typedefs to the lookup table because
- // ASTImporter does not organize typedefs into redecl chains.
- } else if (isa<UsingType>(Ty)) {
- // Similar to TypedefType, not putting into lookup table.
} else {
- llvm_unreachable("Unhandled type of friend class");
+ if (isa<TypedefType>(Ty)) {
+ // We do not put friend typedefs to the lookup table because
+ // ASTImporter does not organize typedefs into redecl chains.
+ } else if (isa<UsingType>(Ty)) {
+ // Similar to TypedefType, not putting into lookup table.
+ } else {
+ llvm_unreachable("Unhandled type of friend class");
+ }
}
}
}
diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp
index 0e2023f..096bc6c 100644
--- a/clang/lib/AST/ASTStructuralEquivalence.cpp
+++ b/clang/lib/AST/ASTStructuralEquivalence.cpp
@@ -110,8 +110,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
const TemplateArgumentLoc &Arg1,
const TemplateArgumentLoc &Arg2);
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
- NestedNameSpecifier *NNS1,
- NestedNameSpecifier *NNS2);
+ NestedNameSpecifier NNS1,
+ NestedNameSpecifier NNS2);
static bool IsStructurallyEquivalent(const IdentifierInfo *Name1,
const IdentifierInfo *Name2);
@@ -579,35 +579,30 @@ static bool IsStructurallyEquivalent(const IdentifierInfo *Name1,
/// Determine whether two nested-name-specifiers are equivalent.
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
- NestedNameSpecifier *NNS1,
- NestedNameSpecifier *NNS2) {
- if (NNS1->getKind() != NNS2->getKind())
- return false;
-
- NestedNameSpecifier *Prefix1 = NNS1->getPrefix(),
- *Prefix2 = NNS2->getPrefix();
- if ((bool)Prefix1 != (bool)Prefix2)
- return false;
-
- if (Prefix1)
- if (!IsStructurallyEquivalent(Context, Prefix1, Prefix2))
- return false;
-
- switch (NNS1->getKind()) {
- case NestedNameSpecifier::Identifier:
- return IsStructurallyEquivalent(NNS1->getAsIdentifier(),
- NNS2->getAsIdentifier());
- case NestedNameSpecifier::Namespace:
- return IsStructurallyEquivalent(Context, NNS1->getAsNamespace(),
- NNS2->getAsNamespace());
- case NestedNameSpecifier::TypeSpec:
- return IsStructurallyEquivalent(Context, QualType(NNS1->getAsType(), 0),
- QualType(NNS2->getAsType(), 0));
- case NestedNameSpecifier::Global:
+ NestedNameSpecifier NNS1,
+ NestedNameSpecifier NNS2) {
+ auto Kind = NNS1.getKind();
+ if (Kind != NNS2.getKind())
+ return false;
+ switch (Kind) {
+ case NestedNameSpecifier::Kind::Null:
+ case NestedNameSpecifier::Kind::Global:
return true;
- case NestedNameSpecifier::Super:
- return IsStructurallyEquivalent(Context, NNS1->getAsRecordDecl(),
- NNS2->getAsRecordDecl());
+ case NestedNameSpecifier::Kind::Namespace: {
+ auto [Namespace1, Prefix1] = NNS1.getAsNamespaceAndPrefix();
+ auto [Namespace2, Prefix2] = NNS2.getAsNamespaceAndPrefix();
+ if (!IsStructurallyEquivalent(Context,
+ const_cast<NamespaceBaseDecl *>(Namespace1),
+ const_cast<NamespaceBaseDecl *>(Namespace2)))
+ return false;
+ return IsStructurallyEquivalent(Context, Prefix1, Prefix2);
+ }
+ case NestedNameSpecifier::Kind::Type:
+ return IsStructurallyEquivalent(Context, QualType(NNS1.getAsType(), 0),
+ QualType(NNS2.getAsType(), 0));
+ case NestedNameSpecifier::Kind::MicrosoftSuper:
+ return IsStructurallyEquivalent(Context, NNS1.getAsMicrosoftSuper(),
+ NNS2.getAsMicrosoftSuper());
}
return false;
}
@@ -615,9 +610,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
const DependentTemplateStorage &S1,
const DependentTemplateStorage &S2) {
- if (NestedNameSpecifier *NNS1 = S1.getQualifier(), *NNS2 = S2.getQualifier();
- !NNS1 != !NNS2 ||
- (NNS1 && !IsStructurallyEquivalent(Context, NNS1, NNS2)))
+ if (!IsStructurallyEquivalent(Context, S1.getQualifier(), S2.getQualifier()))
return false;
IdentifierOrOverloadedOperator IO1 = S1.getName(), IO2 = S2.getName();
@@ -885,10 +878,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
// Treat the enumeration as its underlying type and use the builtin type
// class comparison.
if (T1->getTypeClass() == Type::Enum) {
- T1 = T1->getAs<EnumType>()->getDecl()->getIntegerType();
+ T1 = T1->getAs<EnumType>()->getOriginalDecl()->getIntegerType();
assert(T2->isBuiltinType() && !T1.isNull()); // Sanity check
} else if (T2->getTypeClass() == Type::Enum) {
- T2 = T2->getAs<EnumType>()->getDecl()->getIntegerType();
+ T2 = T2->getAs<EnumType>()->getOriginalDecl()->getIntegerType();
assert(T1->isBuiltinType() && !T2.isNull()); // Sanity check
}
TC = Type::Builtin;
@@ -1206,23 +1199,35 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
return false;
break;
- case Type::Using:
- if (!IsStructurallyEquivalent(Context, cast<UsingType>(T1)->getFoundDecl(),
- cast<UsingType>(T2)->getFoundDecl()))
+ case Type::Using: {
+ auto *U1 = cast<UsingType>(T1), *U2 = cast<UsingType>(T2);
+ if (U1->getKeyword() != U2->getKeyword())
return false;
- if (!IsStructurallyEquivalent(Context,
- cast<UsingType>(T1)->getUnderlyingType(),
- cast<UsingType>(T2)->getUnderlyingType()))
+ if (!IsStructurallyEquivalent(Context, U1->getQualifier(),
+ U2->getQualifier()))
+ return false;
+ if (!IsStructurallyEquivalent(Context, U1->getDecl(), U2->getDecl()))
+ return false;
+ if (!IsStructurallyEquivalent(Context, U1->desugar(), U2->desugar()))
return false;
break;
-
- case Type::Typedef:
- if (!IsStructurallyEquivalent(Context, cast<TypedefType>(T1)->getDecl(),
- cast<TypedefType>(T2)->getDecl()) ||
- !IsStructurallyEquivalent(Context, cast<TypedefType>(T1)->desugar(),
- cast<TypedefType>(T2)->desugar()))
+ }
+ case Type::Typedef: {
+ auto *U1 = cast<TypedefType>(T1), *U2 = cast<TypedefType>(T2);
+ if (U1->getKeyword() != U2->getKeyword())
+ return false;
+ if (!IsStructurallyEquivalent(Context, U1->getQualifier(),
+ U2->getQualifier()))
+ return false;
+ if (!IsStructurallyEquivalent(Context, U1->getDecl(), U2->getDecl()))
+ return false;
+ if (U1->typeMatchesDecl() != U2->typeMatchesDecl())
+ return false;
+ if (!U1->typeMatchesDecl() &&
+ !IsStructurallyEquivalent(Context, U1->desugar(), U2->desugar()))
return false;
break;
+ }
case Type::TypeOfExpr:
if (!IsStructurallyEquivalent(
@@ -1286,10 +1291,20 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
case Type::Record:
case Type::Enum:
- if (!IsStructurallyEquivalent(Context, cast<TagType>(T1)->getDecl(),
- cast<TagType>(T2)->getDecl()))
+ case Type::InjectedClassName: {
+ const auto *TT1 = cast<TagType>(T1), *TT2 = cast<TagType>(T2);
+ if (TT1->getKeyword() != TT2->getKeyword())
+ return false;
+ if (TT1->isTagOwned() != TT2->isTagOwned())
+ return false;
+ if (!IsStructurallyEquivalent(Context, TT1->getQualifier(),
+ TT2->getQualifier()))
+ return false;
+ if (!IsStructurallyEquivalent(Context, TT1->getOriginalDecl(),
+ TT2->getOriginalDecl()))
return false;
break;
+ }
case Type::TemplateTypeParm: {
const auto *Parm1 = cast<TemplateTypeParmType>(T1);
@@ -1348,33 +1363,6 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
break;
}
- case Type::Elaborated: {
- const auto *Elab1 = cast<ElaboratedType>(T1);
- const auto *Elab2 = cast<ElaboratedType>(T2);
- // CHECKME: what if a keyword is ElaboratedTypeKeyword::None or
- // ElaboratedTypeKeyword::Typename
- // ?
- if (Elab1->getKeyword() != Elab2->getKeyword())
- return false;
- if (!IsStructurallyEquivalent(Context, Elab1->getQualifier(),
- Elab2->getQualifier()))
- return false;
- if (!IsStructurallyEquivalent(Context, Elab1->getNamedType(),
- Elab2->getNamedType()))
- return false;
- break;
- }
-
- case Type::InjectedClassName: {
- const auto *Inj1 = cast<InjectedClassNameType>(T1);
- const auto *Inj2 = cast<InjectedClassNameType>(T2);
- if (!IsStructurallyEquivalent(Context,
- Inj1->getInjectedSpecializationType(),
- Inj2->getInjectedSpecializationType()))
- return false;
- break;
- }
-
case Type::DependentName: {
const auto *Typename1 = cast<DependentNameType>(T1);
const auto *Typename2 = cast<DependentNameType>(T2);
@@ -1549,8 +1537,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
// types
if (Field1->isAnonymousStructOrUnion() &&
Field2->isAnonymousStructOrUnion()) {
- RecordDecl *D1 = Field1->getType()->castAs<RecordType>()->getDecl();
- RecordDecl *D2 = Field2->getType()->castAs<RecordType>()->getDecl();
+ RecordDecl *D1 = Field1->getType()->castAs<RecordType>()->getOriginalDecl();
+ RecordDecl *D2 = Field2->getType()->castAs<RecordType>()->getOriginalDecl();
return IsStructurallyEquivalent(Context, D1, D2);
}
@@ -1628,7 +1616,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
FieldDecl *Field1, FieldDecl *Field2) {
const auto *Owner2 = cast<RecordDecl>(Field2->getDeclContext());
return IsStructurallyEquivalent(Context, Field1, Field2,
- Context.ToCtx.getTypeDeclType(Owner2));
+ Context.ToCtx.getCanonicalTagType(Owner2));
}
/// Determine structural equivalence of two methods.
@@ -1801,7 +1789,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
if (Context.Complain) {
Context.Diag2(D2->getLocation(), Context.getApplicableDiagnostic(
diag::err_odr_tag_type_inconsistent))
- << Context.ToCtx.getTypeDeclType(D2)
+ << Context.ToCtx.getCanonicalTagType(D2)
<< (&Context.FromCtx != &Context.ToCtx);
Context.Diag1(D1->getLocation(), diag::note_odr_tag_kind_here)
<< D1->getDeclName() << (unsigned)D1->getTagKind();
@@ -1903,7 +1891,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
Context.Diag2(D2->getLocation(),
Context.getApplicableDiagnostic(
diag::err_odr_tag_type_inconsistent))
- << Context.ToCtx.getTypeDeclType(D2)
+ << Context.ToCtx.getCanonicalTagType(D2)
<< (&Context.FromCtx != &Context.ToCtx);
Context.Diag2(D2->getLocation(), diag::note_odr_number_of_bases)
<< D2CXX->getNumBases();
@@ -1924,7 +1912,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
Context.Diag2(D2->getLocation(),
Context.getApplicableDiagnostic(
diag::err_odr_tag_type_inconsistent))
- << Context.ToCtx.getTypeDeclType(D2)
+ << Context.ToCtx.getCanonicalTagType(D2)
<< (&Context.FromCtx != &Context.ToCtx);
Context.Diag2(Base2->getBeginLoc(), diag::note_odr_base)
<< Base2->getType() << Base2->getSourceRange();
@@ -1940,7 +1928,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
Context.Diag2(D2->getLocation(),
Context.getApplicableDiagnostic(
diag::err_odr_tag_type_inconsistent))
- << Context.ToCtx.getTypeDeclType(D2)
+ << Context.ToCtx.getCanonicalTagType(D2)
<< (&Context.FromCtx != &Context.ToCtx);
Context.Diag2(Base2->getBeginLoc(), diag::note_odr_virtual_base)
<< Base2->isVirtual() << Base2->getSourceRange();
@@ -1962,7 +1950,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
Context.Diag2(D2->getLocation(),
Context.getApplicableDiagnostic(
diag::err_odr_tag_type_inconsistent))
- << Context.ToCtx.getTypeDeclType(D2CXX)
+ << Context.ToCtx.getCanonicalTagType(D2CXX)
<< (&Context.FromCtx != &Context.ToCtx);
Context.Diag1((*Friend1)->getFriendLoc(), diag::note_odr_friend);
Context.Diag2(D2->getLocation(), diag::note_odr_missing_friend);
@@ -1975,7 +1963,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
Context.Diag2(D2->getLocation(),
Context.getApplicableDiagnostic(
diag::err_odr_tag_type_inconsistent))
- << Context.ToCtx.getTypeDeclType(D2CXX)
+ << Context.ToCtx.getCanonicalTagType(D2CXX)
<< (&Context.FromCtx != &Context.ToCtx);
Context.Diag1((*Friend1)->getFriendLoc(), diag::note_odr_friend);
Context.Diag2((*Friend2)->getFriendLoc(), diag::note_odr_friend);
@@ -1989,7 +1977,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
Context.Diag2(D2->getLocation(),
Context.getApplicableDiagnostic(
diag::err_odr_tag_type_inconsistent))
- << Context.ToCtx.getTypeDeclType(D2)
+ << Context.ToCtx.getCanonicalTagType(D2)
<< (&Context.FromCtx != &Context.ToCtx);
Context.Diag2((*Friend2)->getFriendLoc(), diag::note_odr_friend);
Context.Diag1(D1->getLocation(), diag::note_odr_missing_friend);
@@ -2001,7 +1989,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
Context.Diag2(D2->getLocation(),
Context.getApplicableDiagnostic(
diag::err_odr_tag_type_inconsistent))
- << Context.ToCtx.getTypeDeclType(D2)
+ << Context.ToCtx.getCanonicalTagType(D2)
<< (&Context.FromCtx != &Context.ToCtx);
const CXXBaseSpecifier *Base1 = D1CXX->bases_begin();
Context.Diag1(Base1->getBeginLoc(), diag::note_odr_base)
@@ -2013,7 +2001,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
}
// Check the fields for consistency.
- QualType D2Type = Context.ToCtx.getTypeDeclType(D2);
+ CanQualType D2Type = Context.ToCtx.getCanonicalTagType(D2);
RecordDecl::field_iterator Field2 = D2->field_begin(),
Field2End = D2->field_end();
for (RecordDecl::field_iterator Field1 = D1->field_begin(),
@@ -2024,7 +2012,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
Context.Diag2(D2->getLocation(),
Context.getApplicableDiagnostic(
diag::err_odr_tag_type_inconsistent))
- << Context.ToCtx.getTypeDeclType(D2)
+ << Context.ToCtx.getCanonicalTagType(D2)
<< (&Context.FromCtx != &Context.ToCtx);
Context.Diag1(Field1->getLocation(), diag::note_odr_field)
<< Field1->getDeclName() << Field1->getType();
@@ -2041,7 +2029,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
if (Context.Complain) {
Context.Diag2(D2->getLocation(), Context.getApplicableDiagnostic(
diag::err_odr_tag_type_inconsistent))
- << Context.ToCtx.getTypeDeclType(D2)
+ << Context.ToCtx.getCanonicalTagType(D2)
<< (&Context.FromCtx != &Context.ToCtx);
Context.Diag2(Field2->getLocation(), diag::note_odr_field)
<< Field2->getDeclName() << Field2->getType();
@@ -2101,7 +2089,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
Context.Diag2(D2->getLocation(),
Context.getApplicableDiagnostic(
diag::err_odr_tag_type_inconsistent))
- << Context.ToCtx.getTypeDeclType(D2)
+ << Context.ToCtx.getCanonicalTagType(D2)
<< (&Context.FromCtx != &Context.ToCtx);
Context.Diag1(D1->getLocation(),
D1->isFixed()
@@ -2124,7 +2112,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
Context.Diag2(D2->getLocation(),
Context.getApplicableDiagnostic(
diag::err_odr_tag_type_inconsistent))
- << Context.ToCtx.getTypeDeclType(D2)
+ << Context.ToCtx.getCanonicalTagType(D2)
<< (&Context.FromCtx != &Context.ToCtx);
Context.Diag2(D2->getLocation(),
diag::note_odr_incompatible_fixed_underlying_type)
@@ -2162,7 +2150,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
Context.Diag2(D2->getLocation(),
Context.getApplicableDiagnostic(
diag::err_odr_tag_type_inconsistent))
- << Context.ToCtx.getTypeDeclType(D2)
+ << Context.ToCtx.getCanonicalTagType(D2)
<< (&Context.FromCtx != &Context.ToCtx);
Context.Diag1((*EC1)->getLocation(), diag::note_odr_enumerator)
<< (*EC1)->getDeclName() << toString((*EC1)->getInitVal(), 10);
@@ -2180,7 +2168,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
Context.Diag2(D2->getLocation(),
Context.getApplicableDiagnostic(
diag::err_odr_tag_type_inconsistent))
- << Context.ToCtx.getTypeDeclType(D2)
+ << Context.ToCtx.getCanonicalTagType(D2)
<< (&Context.FromCtx != &Context.ToCtx);
Context.Diag2((*EC2)->getLocation(), diag::note_odr_enumerator)
<< (*EC2)->getDeclName() << toString((*EC2)->getInitVal(), 10);
@@ -2198,7 +2186,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
if (Context.Complain) {
Context.Diag2(D2->getLocation(), Context.getApplicableDiagnostic(
diag::err_odr_tag_type_inconsistent))
- << Context.ToCtx.getTypeDeclType(D2)
+ << Context.ToCtx.getCanonicalTagType(D2)
<< (&Context.FromCtx != &Context.ToCtx);
Context.Diag2((*EC2)->getLocation(), diag::note_odr_enumerator)
<< (*EC2)->getDeclName() << toString((*EC2)->getInitVal(), 10);
@@ -2595,7 +2583,7 @@ DiagnosticBuilder StructuralEquivalenceContext::Diag2(SourceLocation Loc,
UnsignedOrNone
StructuralEquivalenceContext::findUntaggedStructOrUnionIndex(RecordDecl *Anon) {
ASTContext &Context = Anon->getASTContext();
- QualType AnonTy = Context.getRecordType(Anon);
+ CanQualType AnonTy = Context.getCanonicalTagType(Anon);
const auto *Owner = dyn_cast<RecordDecl>(Anon->getDeclContext());
if (!Owner)
@@ -2617,12 +2605,8 @@ StructuralEquivalenceContext::findUntaggedStructOrUnionIndex(RecordDecl *Anon) {
// If the field looks like this:
// struct { ... } A;
QualType FieldType = F->getType();
- // In case of nested structs.
- while (const auto *ElabType = dyn_cast<ElaboratedType>(FieldType))
- FieldType = ElabType->getNamedType();
-
if (const auto *RecType = dyn_cast<RecordType>(FieldType)) {
- const RecordDecl *RecDecl = RecType->getDecl();
+ const RecordDecl *RecDecl = RecType->getOriginalDecl();
if (RecDecl->getDeclContext() == Owner && !RecDecl->getIdentifier()) {
if (Context.hasSameType(FieldType, AnonTy))
break;
diff --git a/clang/lib/AST/ASTTypeTraits.cpp b/clang/lib/AST/ASTTypeTraits.cpp
index 99916f5..d2f7fdb 100644
--- a/clang/lib/AST/ASTTypeTraits.cpp
+++ b/clang/lib/AST/ASTTypeTraits.cpp
@@ -194,8 +194,8 @@ void DynTypedNode::print(llvm::raw_ostream &OS,
else if (const NestedNameSpecifier *NNS = get<NestedNameSpecifier>())
NNS->print(OS, PP);
else if (const NestedNameSpecifierLoc *NNSL = get<NestedNameSpecifierLoc>()) {
- if (const NestedNameSpecifier *NNS = NNSL->getNestedNameSpecifier())
- NNS->print(OS, PP);
+ if (NestedNameSpecifier NNS = NNSL->getNestedNameSpecifier())
+ NNS.print(OS, PP);
else
OS << "(empty NestedNameSpecifierLoc)";
} else if (const QualType *QT = get<QualType>())
@@ -234,13 +234,39 @@ void DynTypedNode::dump(llvm::raw_ostream &OS,
OS << "Unable to dump values of type " << NodeKind.asStringRef() << "\n";
}
-SourceRange DynTypedNode::getSourceRange() const {
+SourceRange DynTypedNode::getSourceRange(bool IncludeQualifier) const {
if (const CXXCtorInitializer *CCI = get<CXXCtorInitializer>())
return CCI->getSourceRange();
if (const NestedNameSpecifierLoc *NNSL = get<NestedNameSpecifierLoc>())
return NNSL->getSourceRange();
- if (const TypeLoc *TL = get<TypeLoc>())
- return TL->getSourceRange();
+ if (const TypeLoc *TL = get<TypeLoc>()) {
+ if (IncludeQualifier)
+ return TL->getSourceRange();
+ switch (TL->getTypeLocClass()) {
+ case TypeLoc::DependentName:
+ return TL->castAs<DependentNameTypeLoc>().getNameLoc();
+ case TypeLoc::TemplateSpecialization: {
+ auto T = TL->castAs<TemplateSpecializationTypeLoc>();
+ return SourceRange(T.getTemplateNameLoc(), T.getEndLoc());
+ }
+ case TypeLoc::DependentTemplateSpecialization: {
+ auto T = TL->castAs<DependentTemplateSpecializationTypeLoc>();
+ return SourceRange(T.getTemplateNameLoc(), T.getEndLoc());
+ }
+ case TypeLoc::Enum:
+ case TypeLoc::Record:
+ case TypeLoc::InjectedClassName:
+ return TL->castAs<TagTypeLoc>().getNameLoc();
+ case TypeLoc::Typedef:
+ return TL->castAs<TypedefTypeLoc>().getNameLoc();
+ case TypeLoc::UnresolvedUsing:
+ return TL->castAs<UnresolvedUsingTypeLoc>().getNameLoc();
+ case TypeLoc::Using:
+ return TL->castAs<UsingTypeLoc>().getNameLoc();
+ default:
+ return TL->getSourceRange();
+ }
+ }
if (const Decl *D = get<Decl>())
return D->getSourceRange();
if (const Stmt *S = get<Stmt>())
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 4ab4dee..f131ac1 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -553,9 +553,10 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
// Possibly diagnose casts to enum types if the target type does not
// have a fixed size.
if (Ctx.getLangOpts().CPlusPlus && CE->getType()->isEnumeralType()) {
- if (const auto *ET = CE->getType().getCanonicalType()->castAs<EnumType>();
- !ET->getDecl()->isFixed()) {
- if (!this->emitCheckEnumValue(*FromT, ET->getDecl(), CE))
+ const auto *ET = CE->getType().getCanonicalType()->castAs<EnumType>();
+ const auto *ED = ET->getOriginalDecl()->getDefinitionOrSelf();
+ if (!ED->isFixed()) {
+ if (!this->emitCheckEnumValue(*FromT, ED, CE))
return false;
}
}
@@ -666,8 +667,8 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
}
case CK_VectorSplat: {
- assert(!classify(CE->getType()));
- assert(classify(SubExpr->getType()));
+ assert(!canClassify(CE->getType()));
+ assert(canClassify(SubExpr->getType()));
assert(CE->getType()->isVectorType());
if (!Initializing) {
@@ -2063,16 +2064,13 @@ bool Compiler<Emitter>::visitCallArgs(ArrayRef<const Expr *> Args,
const FunctionDecl *FuncDecl,
bool Activate) {
assert(VarScope->getKind() == ScopeKind::Call);
- bool HasNonNullAttr = false;
llvm::BitVector NonNullArgs;
- if (FuncDecl && FuncDecl->hasAttr<NonNullAttr>()) {
- HasNonNullAttr = true;
+ if (FuncDecl && FuncDecl->hasAttr<NonNullAttr>())
NonNullArgs = collectNonNullArgs(FuncDecl, Args);
- }
unsigned ArgIndex = 0;
for (const Expr *Arg : Args) {
- if (OptPrimType T = classify(Arg)) {
+ if (canClassify(Arg)) {
if (!this->visit(Arg))
return false;
} else {
@@ -2094,7 +2092,7 @@ bool Compiler<Emitter>::visitCallArgs(ArrayRef<const Expr *> Args,
return false;
}
- if (HasNonNullAttr && NonNullArgs[ArgIndex]) {
+ if (!NonNullArgs.empty() && NonNullArgs[ArgIndex]) {
PrimType ArgT = classify(Arg).value_or(PT_Ptr);
if (ArgT == PT_Ptr) {
if (!this->emitCheckNonNullArg(ArgT, Arg))
@@ -3157,7 +3155,7 @@ bool Compiler<Emitter>::VisitCXXNoexceptExpr(const CXXNoexceptExpr *E) {
template <class Emitter>
bool Compiler<Emitter>::VisitCXXConstructExpr(const CXXConstructExpr *E) {
QualType T = E->getType();
- assert(!classify(T));
+ assert(!canClassify(T));
if (T->isRecordType()) {
const CXXConstructorDecl *Ctor = E->getConstructor();
@@ -4152,7 +4150,7 @@ template <class Emitter> bool Compiler<Emitter>::visit(const Expr *E) {
// Create local variable to hold the return value.
if (!E->isGLValue() && !E->getType()->isAnyComplexType() &&
- !classify(E->getType())) {
+ !canClassify(E->getType())) {
std::optional<unsigned> LocalIndex = allocateLocal(E);
if (!LocalIndex)
return false;
@@ -4172,7 +4170,7 @@ template <class Emitter> bool Compiler<Emitter>::visit(const Expr *E) {
template <class Emitter>
bool Compiler<Emitter>::visitInitializer(const Expr *E) {
- assert(!classify(E->getType()));
+ assert(!canClassify(E->getType()));
OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/false,
/*NewInitializing=*/true);
@@ -4379,7 +4377,7 @@ bool Compiler<Emitter>::visitZeroArrayInitializer(QualType T, const Expr *E) {
template <class Emitter>
bool Compiler<Emitter>::visitAssignment(const Expr *LHS, const Expr *RHS,
const Expr *E) {
- if (!classify(E->getType()))
+ if (!canClassify(E->getType()))
return false;
if (!this->visit(RHS))
@@ -4592,7 +4590,7 @@ const RecordType *Compiler<Emitter>::getRecordTy(QualType Ty) {
template <class Emitter> Record *Compiler<Emitter>::getRecord(QualType Ty) {
if (const auto *RecordTy = getRecordTy(Ty))
- return getRecord(RecordTy->getDecl());
+ return getRecord(RecordTy->getOriginalDecl()->getDefinitionOrSelf());
return nullptr;
}
@@ -5997,6 +5995,23 @@ bool Compiler<Emitter>::checkLiteralType(const Expr *E) {
return this->emitCheckLiteralType(E->getType().getTypePtr(), E);
}
+static bool initNeedsOverridenLoc(const CXXCtorInitializer *Init) {
+ const Expr *InitExpr = Init->getInit();
+
+ if (!Init->isWritten() && !Init->isInClassMemberInitializer() &&
+ !isa<CXXConstructExpr>(InitExpr))
+ return true;
+
+ if (const auto *CE = dyn_cast<CXXConstructExpr>(InitExpr)) {
+ const CXXConstructorDecl *Ctor = CE->getConstructor();
+ if (Ctor->isDefaulted() && Ctor->isCopyOrMoveConstructor() &&
+ Ctor->isTrivial())
+ return true;
+ }
+
+ return false;
+}
+
template <class Emitter>
bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) {
assert(!ReturnType);
@@ -6071,10 +6086,7 @@ bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) {
const Record::Field *F = R->getField(Member);
LocOverrideScope<Emitter> LOS(this, SourceInfo{},
- !Init->isWritten() &&
- !Init->isInClassMemberInitializer() &&
- (!isa<CXXConstructExpr>(InitExpr) ||
- Member->isAnonymousStructOrUnion()));
+ initNeedsOverridenLoc(Init));
if (!emitFieldInitializer(F, F->Offset, InitExpr, IsUnion))
return false;
} else if (const Type *Base = Init->getBaseClass()) {
@@ -6104,10 +6116,7 @@ bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) {
return false;
} else if (const IndirectFieldDecl *IFD = Init->getIndirectMember()) {
LocOverrideScope<Emitter> LOS(this, SourceInfo{},
- !Init->isWritten() &&
- !Init->isInClassMemberInitializer() &&
- !isa<CXXConstructExpr>(InitExpr));
-
+ initNeedsOverridenLoc(Init));
assert(IFD->getChainingSize() >= 2);
unsigned NestedFieldOffset = 0;
@@ -7131,10 +7140,6 @@ bool Compiler<Emitter>::emitDestruction(const Descriptor *Desc,
assert(!Desc->isPrimitive());
assert(!Desc->isPrimitiveArray());
- // Can happen if the decl is invalid.
- if (Desc->isDummy())
- return true;
-
// Arrays.
if (Desc->isArray()) {
const Descriptor *ElemDesc = Desc->ElemDesc;
diff --git a/clang/lib/AST/ByteCode/Compiler.h b/clang/lib/AST/ByteCode/Compiler.h
index ee8327d..d72ffa1 100644
--- a/clang/lib/AST/ByteCode/Compiler.h
+++ b/clang/lib/AST/ByteCode/Compiler.h
@@ -256,6 +256,8 @@ protected:
OptPrimType classify(const Expr *E) const { return Ctx.classify(E); }
OptPrimType classify(QualType Ty) const { return Ctx.classify(Ty); }
+ bool canClassify(const Expr *E) const { return Ctx.canClassify(E); }
+ bool canClassify(QualType T) const { return Ctx.canClassify(T); }
/// Classifies a known primitive type.
PrimType classifyPrim(QualType Ty) const {
diff --git a/clang/lib/AST/ByteCode/Context.cpp b/clang/lib/AST/ByteCode/Context.cpp
index f7f528c..6343b2a 100644
--- a/clang/lib/AST/ByteCode/Context.cpp
+++ b/clang/lib/AST/ByteCode/Context.cpp
@@ -365,7 +365,7 @@ OptPrimType Context::classify(QualType T) const {
}
if (const auto *ET = T->getAs<EnumType>()) {
- const auto *D = ET->getDecl();
+ const auto *D = ET->getOriginalDecl()->getDefinitionOrSelf();
if (!D->isComplete())
return std::nullopt;
return classify(D->getIntegerType());
@@ -501,7 +501,7 @@ const Function *Context::getOrCreateFunction(const FunctionDecl *FuncDecl) {
// elsewhere in the code.
QualType Ty = FuncDecl->getReturnType();
bool HasRVO = false;
- if (!Ty->isVoidType() && !classify(Ty)) {
+ if (!Ty->isVoidType() && !canClassify(Ty)) {
HasRVO = true;
ParamTypes.push_back(PT_Ptr);
ParamOffsets.push_back(ParamOffset);
diff --git a/clang/lib/AST/ByteCode/Context.h b/clang/lib/AST/ByteCode/Context.h
index 1c084ac..a6d90bb 100644
--- a/clang/lib/AST/ByteCode/Context.h
+++ b/clang/lib/AST/ByteCode/Context.h
@@ -93,6 +93,25 @@ public:
return classify(E->getType());
}
+ bool canClassify(QualType T) {
+ if (const auto *BT = dyn_cast<BuiltinType>(T)) {
+ if (BT->isInteger() || BT->isFloatingPoint())
+ return true;
+ if (BT->getKind() == BuiltinType::Bool)
+ return true;
+ }
+
+ if (T->isArrayType() || T->isRecordType() || T->isAnyComplexType() ||
+ T->isVectorType())
+ return false;
+ return classify(T) != std::nullopt;
+ }
+ bool canClassify(const Expr *E) {
+ if (E->isGLValue())
+ return true;
+ return canClassify(E->getType());
+ }
+
const CXXMethodDecl *
getOverridingFunction(const CXXRecordDecl *DynamicDecl,
const CXXRecordDecl *StaticDecl,
diff --git a/clang/lib/AST/ByteCode/Descriptor.cpp b/clang/lib/AST/ByteCode/Descriptor.cpp
index 7403e90..234fa2c 100644
--- a/clang/lib/AST/ByteCode/Descriptor.cpp
+++ b/clang/lib/AST/ByteCode/Descriptor.cpp
@@ -153,28 +153,6 @@ static void dtorArrayDesc(Block *B, std::byte *Ptr, const Descriptor *D) {
}
}
-static void moveArrayDesc(Block *B, std::byte *Src, std::byte *Dst,
- const Descriptor *D) {
- const unsigned NumElems = D->getNumElems();
- const unsigned ElemSize =
- D->ElemDesc->getAllocSize() + sizeof(InlineDescriptor);
-
- unsigned ElemOffset = 0;
- for (unsigned I = 0; I < NumElems; ++I, ElemOffset += ElemSize) {
- auto *SrcPtr = Src + ElemOffset;
- auto *DstPtr = Dst + ElemOffset;
-
- auto *SrcDesc = reinterpret_cast<InlineDescriptor *>(SrcPtr);
- auto *SrcElemLoc = reinterpret_cast<std::byte *>(SrcDesc + 1);
- auto *DstDesc = reinterpret_cast<InlineDescriptor *>(DstPtr);
- auto *DstElemLoc = reinterpret_cast<std::byte *>(DstDesc + 1);
-
- *DstDesc = *SrcDesc;
- if (auto Fn = D->ElemDesc->MoveFn)
- Fn(B, SrcElemLoc, DstElemLoc, D->ElemDesc);
- }
-}
-
static void initField(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable,
bool IsVolatile, bool IsActive, bool IsUnionField,
bool InUnion, const Descriptor *D, unsigned FieldOffset) {
@@ -268,45 +246,6 @@ static void dtorRecord(Block *B, std::byte *Ptr, const Descriptor *D) {
destroyBase(B, Ptr, F.Desc, F.Offset);
}
-static void moveRecord(Block *B, std::byte *Src, std::byte *Dst,
- const Descriptor *D) {
- assert(D);
- assert(D->ElemRecord);
-
- // FIXME: Code duplication.
- for (const auto &F : D->ElemRecord->fields()) {
- auto FieldOffset = F.Offset;
- const auto *SrcDesc =
- reinterpret_cast<const InlineDescriptor *>(Src + FieldOffset) - 1;
- auto *DestDesc =
- reinterpret_cast<InlineDescriptor *>(Dst + FieldOffset) - 1;
- std::memcpy(DestDesc, SrcDesc, sizeof(InlineDescriptor));
-
- if (auto Fn = F.Desc->MoveFn)
- Fn(B, Src + FieldOffset, Dst + FieldOffset, F.Desc);
- }
-
- for (const auto &Base : D->ElemRecord->bases()) {
- auto BaseOffset = Base.Offset;
- const auto *SrcDesc =
- reinterpret_cast<const InlineDescriptor *>(Src + BaseOffset) - 1;
- auto *DestDesc = reinterpret_cast<InlineDescriptor *>(Dst + BaseOffset) - 1;
- std::memcpy(DestDesc, SrcDesc, sizeof(InlineDescriptor));
-
- if (auto Fn = Base.Desc->MoveFn)
- Fn(B, Src + BaseOffset, Dst + BaseOffset, Base.Desc);
- }
-
- for (const auto &VBase : D->ElemRecord->virtual_bases()) {
- auto VBaseOffset = VBase.Offset;
- const auto *SrcDesc =
- reinterpret_cast<const InlineDescriptor *>(Src + VBaseOffset) - 1;
- auto *DestDesc =
- reinterpret_cast<InlineDescriptor *>(Dst + VBaseOffset) - 1;
- std::memcpy(DestDesc, SrcDesc, sizeof(InlineDescriptor));
- }
-}
-
static BlockCtorFn getCtorPrim(PrimType Type) {
// Floating types are special. They are primitives, but need their
// constructor called.
@@ -337,18 +276,6 @@ static BlockDtorFn getDtorPrim(PrimType Type) {
COMPOSITE_TYPE_SWITCH(Type, return dtorTy<T>, return nullptr);
}
-static BlockMoveFn getMovePrim(PrimType Type) {
- if (Type == PT_Float)
- return moveTy<PrimConv<PT_Float>::T>;
- if (Type == PT_IntAP)
- return moveTy<PrimConv<PT_IntAP>::T>;
- if (Type == PT_IntAPS)
- return moveTy<PrimConv<PT_IntAPS>::T>;
- if (Type == PT_MemberPtr)
- return moveTy<PrimConv<PT_MemberPtr>::T>;
- COMPOSITE_TYPE_SWITCH(Type, return moveTy<T>, return nullptr);
-}
-
static BlockCtorFn getCtorArrayPrim(PrimType Type) {
TYPE_SWITCH(Type, return ctorArrayTy<T>);
llvm_unreachable("unknown Expr");
@@ -359,11 +286,6 @@ static BlockDtorFn getDtorArrayPrim(PrimType Type) {
llvm_unreachable("unknown Expr");
}
-static BlockMoveFn getMoveArrayPrim(PrimType Type) {
- TYPE_SWITCH(Type, return moveArrayTy<T>);
- llvm_unreachable("unknown Expr");
-}
-
/// Primitives.
Descriptor::Descriptor(const DeclTy &D, const Type *SourceTy, PrimType Type,
MetadataSize MD, bool IsConst, bool IsTemporary,
@@ -372,7 +294,7 @@ Descriptor::Descriptor(const DeclTy &D, const Type *SourceTy, PrimType Type,
MDSize(MD.value_or(0)), AllocSize(align(Size + MDSize)), PrimT(Type),
IsConst(IsConst), IsMutable(IsMutable), IsTemporary(IsTemporary),
IsVolatile(IsVolatile), CtorFn(getCtorPrim(Type)),
- DtorFn(getDtorPrim(Type)), MoveFn(getMovePrim(Type)) {
+ DtorFn(getDtorPrim(Type)) {
assert(AllocSize >= Size);
assert(Source && "Missing source");
}
@@ -386,7 +308,7 @@ Descriptor::Descriptor(const DeclTy &D, PrimType Type, MetadataSize MD,
AllocSize(align(MDSize) + align(Size) + sizeof(InitMapPtr)), PrimT(Type),
IsConst(IsConst), IsMutable(IsMutable), IsTemporary(IsTemporary),
IsArray(true), CtorFn(getCtorArrayPrim(Type)),
- DtorFn(getDtorArrayPrim(Type)), MoveFn(getMoveArrayPrim(Type)) {
+ DtorFn(getDtorArrayPrim(Type)) {
assert(Source && "Missing source");
assert(NumElems <= (MaxArrayElemBytes / ElemSize));
}
@@ -399,7 +321,7 @@ Descriptor::Descriptor(const DeclTy &D, PrimType Type, MetadataSize MD,
AllocSize(MDSize + sizeof(InitMapPtr) + alignof(void *)), PrimT(Type),
IsConst(IsConst), IsMutable(false), IsTemporary(IsTemporary),
IsArray(true), CtorFn(getCtorArrayPrim(Type)),
- DtorFn(getDtorArrayPrim(Type)), MoveFn(getMoveArrayPrim(Type)) {
+ DtorFn(getDtorArrayPrim(Type)) {
assert(Source && "Missing source");
}
@@ -414,7 +336,7 @@ Descriptor::Descriptor(const DeclTy &D, const Type *SourceTy,
AllocSize(std::max<size_t>(alignof(void *), Size) + MDSize),
ElemDesc(Elem), IsConst(IsConst), IsMutable(IsMutable),
IsTemporary(IsTemporary), IsArray(true), CtorFn(ctorArrayDesc),
- DtorFn(dtorArrayDesc), MoveFn(moveArrayDesc) {
+ DtorFn(dtorArrayDesc) {
assert(Source && "Missing source");
}
@@ -425,7 +347,7 @@ Descriptor::Descriptor(const DeclTy &D, const Descriptor *Elem, MetadataSize MD,
Size(UnknownSizeMark), MDSize(MD.value_or(0)),
AllocSize(MDSize + alignof(void *)), ElemDesc(Elem), IsConst(true),
IsMutable(false), IsTemporary(IsTemporary), IsArray(true),
- CtorFn(ctorArrayDesc), DtorFn(dtorArrayDesc), MoveFn(moveArrayDesc) {
+ CtorFn(ctorArrayDesc), DtorFn(dtorArrayDesc) {
assert(Source && "Missing source");
}
@@ -437,7 +359,7 @@ Descriptor::Descriptor(const DeclTy &D, const Record *R, MetadataSize MD,
Size(ElemSize), MDSize(MD.value_or(0)), AllocSize(Size + MDSize),
ElemRecord(R), IsConst(IsConst), IsMutable(IsMutable),
IsTemporary(IsTemporary), IsVolatile(IsVolatile), CtorFn(ctorRecord),
- DtorFn(dtorRecord), MoveFn(moveRecord) {
+ DtorFn(dtorRecord) {
assert(Source && "Missing source");
}
@@ -445,7 +367,7 @@ Descriptor::Descriptor(const DeclTy &D, const Record *R, MetadataSize MD,
Descriptor::Descriptor(const DeclTy &D, MetadataSize MD)
: Source(D), ElemSize(1), Size(1), MDSize(MD.value_or(0)),
AllocSize(MDSize), ElemRecord(nullptr), IsConst(true), IsMutable(false),
- IsTemporary(false), IsDummy(true) {
+ IsTemporary(false) {
assert(Source && "Missing source");
}
@@ -455,12 +377,14 @@ QualType Descriptor::getType() const {
if (const auto *D = asValueDecl())
return D->getType();
if (const auto *T = dyn_cast_if_present<TypeDecl>(asDecl()))
- return QualType(T->getTypeForDecl(), 0);
+ return T->getASTContext().getTypeDeclType(T);
// The Source sometimes has a different type than the once
// we really save. Try to consult the Record first.
- if (isRecord())
- return QualType(ElemRecord->getDecl()->getTypeForDecl(), 0);
+ if (isRecord()) {
+ const RecordDecl *RD = ElemRecord->getDecl();
+ return RD->getASTContext().getCanonicalTagType(RD);
+ }
if (const auto *E = asExpr())
return E->getType();
llvm_unreachable("Invalid descriptor type");
@@ -531,7 +455,7 @@ SourceInfo Descriptor::getLoc() const {
}
bool Descriptor::hasTrivialDtor() const {
- if (isPrimitive() || isPrimitiveArray() || isDummy())
+ if (isPrimitive() || isPrimitiveArray())
return true;
if (isRecord()) {
@@ -540,8 +464,9 @@ bool Descriptor::hasTrivialDtor() const {
return !Dtor || Dtor->isTrivial();
}
+ if (!ElemDesc)
+ return true;
// Composite arrays.
- assert(ElemDesc);
return ElemDesc->hasTrivialDtor();
}
diff --git a/clang/lib/AST/ByteCode/Descriptor.h b/clang/lib/AST/ByteCode/Descriptor.h
index 4c925f6..4a808c0 100644
--- a/clang/lib/AST/ByteCode/Descriptor.h
+++ b/clang/lib/AST/ByteCode/Descriptor.h
@@ -41,14 +41,6 @@ using BlockCtorFn = void (*)(Block *Storage, std::byte *FieldPtr, bool IsConst,
using BlockDtorFn = void (*)(Block *Storage, std::byte *FieldPtr,
const Descriptor *FieldDesc);
-/// Invoked when a block with pointers referencing it goes out of scope. Such
-/// blocks are persisted: the move function copies all inline descriptors and
-/// non-trivial fields, as existing pointers might need to reference those
-/// descriptors. Data is not copied since it cannot be legally read.
-using BlockMoveFn = void (*)(Block *Storage, std::byte *SrcFieldPtr,
- std::byte *DstFieldPtr,
- const Descriptor *FieldDesc);
-
enum class GlobalInitState {
Initialized,
NoInitializer,
@@ -174,14 +166,11 @@ public:
const bool IsVolatile = false;
/// Flag indicating if the block is an array.
const bool IsArray = false;
- /// Flag indicating if this is a dummy descriptor.
- bool IsDummy = false;
bool IsConstexprUnknown = false;
/// Storage management methods.
const BlockCtorFn CtorFn = nullptr;
const BlockDtorFn DtorFn = nullptr;
- const BlockMoveFn MoveFn = nullptr;
/// Allocates a descriptor for a primitive.
Descriptor(const DeclTy &D, const Type *SourceTy, PrimType Type,
@@ -212,9 +201,6 @@ public:
/// Allocates a dummy descriptor.
Descriptor(const DeclTy &D, MetadataSize MD = std::nullopt);
- /// Make this descriptor a dummy descriptor.
- void makeDummy() { IsDummy = true; }
-
QualType getType() const;
QualType getElemQualType() const;
QualType getDataType(const ASTContext &Ctx) const;
@@ -282,8 +268,6 @@ public:
bool isRecord() const { return !IsArray && ElemRecord; }
/// Checks if the descriptor is of a union.
bool isUnion() const;
- /// Checks if this is a dummy descriptor.
- bool isDummy() const { return IsDummy; }
/// Whether variables of this descriptor need their destructor called or not.
bool hasTrivialDtor() const;
diff --git a/clang/lib/AST/ByteCode/Disasm.cpp b/clang/lib/AST/ByteCode/Disasm.cpp
index 5049a65..8eb785d 100644
--- a/clang/lib/AST/ByteCode/Disasm.cpp
+++ b/clang/lib/AST/ByteCode/Disasm.cpp
@@ -338,7 +338,7 @@ LLVM_DUMP_METHOD void Program::dump(llvm::raw_ostream &OS) const {
}
OS << "\n";
- if (GP.isInitialized() && Desc->isPrimitive() && !Desc->isDummy()) {
+ if (GP.isInitialized() && Desc->isPrimitive() && !G->block()->isDummy()) {
OS << " ";
{
ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_CYAN, false});
@@ -394,8 +394,6 @@ LLVM_DUMP_METHOD void Descriptor::dump(llvm::raw_ostream &OS) const {
else if (isUnknownSizeArray())
OS << " unknown-size-array";
- if (isDummy())
- OS << " dummy";
if (IsConstexprUnknown)
OS << " constexpr-unknown";
}
@@ -541,11 +539,12 @@ LLVM_DUMP_METHOD void Block::dump(llvm::raw_ostream &OS) const {
else
OS << "-\n";
OS << " Pointers: " << NPointers << "\n";
- OS << " Dead: " << IsDead << "\n";
+ OS << " Dead: " << isDead() << "\n";
OS << " Static: " << IsStatic << "\n";
- OS << " Extern: " << IsExtern << "\n";
+ OS << " Extern: " << isExtern() << "\n";
OS << " Initialized: " << IsInitialized << "\n";
- OS << " Weak: " << IsWeak << "\n";
+ OS << " Weak: " << isWeak() << "\n";
+ OS << " Dummy: " << isDummy() << '\n';
OS << " Dynamic: " << IsDynamic << "\n";
}
diff --git a/clang/lib/AST/ByteCode/DynamicAllocator.cpp b/clang/lib/AST/ByteCode/DynamicAllocator.cpp
index 9b8b664..2d62ce7 100644
--- a/clang/lib/AST/ByteCode/DynamicAllocator.cpp
+++ b/clang/lib/AST/ByteCode/DynamicAllocator.cpp
@@ -13,25 +13,6 @@
using namespace clang;
using namespace clang::interp;
-// FIXME: There is a peculiar problem with the way we track pointers
-// to blocks and the way we allocate dynamic memory.
-//
-// When we have code like this:
-// while (true) {
-// char *buffer = new char[1024];
-// delete[] buffer;
-// }
-//
-// We have a local variable 'buffer' pointing to the heap allocated memory.
-// When deallocating the memory via delete[], that local variable still
-// points to the memory, which means we will create a DeadBlock for it and move
-// it over to that block, essentially duplicating the allocation. Moving
-// the data is also slow.
-//
-// However, when we actually try to access the allocation after it has been
-// freed, we need the block to still exist (alive or dead) so we can tell
-// that it's a dynamic allocation.
-
DynamicAllocator::~DynamicAllocator() { cleanup(); }
void DynamicAllocator::cleanup() {
@@ -42,8 +23,11 @@ void DynamicAllocator::cleanup() {
for (auto &Iter : AllocationSites) {
auto &AllocSite = Iter.second;
for (auto &Alloc : AllocSite.Allocations) {
- Block *B = reinterpret_cast<Block *>(Alloc.Memory.get());
+ Block *B = Alloc.block();
+ assert(!B->isDead());
+ assert(B->isInitialized());
B->invokeDtor();
+
if (B->hasPointers()) {
while (B->Pointers) {
Pointer *Next = B->Pointers->asBlockPointer().Next;
@@ -89,6 +73,12 @@ Block *DynamicAllocator::allocate(const Descriptor *D, unsigned EvalID,
assert(D);
assert(D->asExpr());
+ // Garbage collection. Remove all dead allocations that don't have pointers to
+ // them anymore.
+ llvm::erase_if(DeadAllocations, [](Allocation &Alloc) -> bool {
+ return !Alloc.block()->hasPointers();
+ });
+
auto Memory =
std::make_unique<std::byte[]>(sizeof(Block) + D->getAllocSize());
auto *B = new (Memory.get()) Block(EvalID, D, /*isStatic=*/false);
@@ -128,23 +118,39 @@ bool DynamicAllocator::deallocate(const Expr *Source,
return false;
auto &Site = It->second;
- assert(Site.size() > 0);
+ assert(!Site.empty());
// Find the Block to delete.
- auto AllocIt = llvm::find_if(Site.Allocations, [&](const Allocation &A) {
- const Block *B = reinterpret_cast<const Block *>(A.Memory.get());
- return BlockToDelete == B;
+ auto *AllocIt = llvm::find_if(Site.Allocations, [&](const Allocation &A) {
+ return BlockToDelete == A.block();
});
assert(AllocIt != Site.Allocations.end());
- Block *B = reinterpret_cast<Block *>(AllocIt->Memory.get());
+ Block *B = AllocIt->block();
+ assert(B->isInitialized());
+ assert(!B->isDead());
B->invokeDtor();
- S.deallocate(B);
- Site.Allocations.erase(AllocIt);
+ // Almost all our dynamic allocations have a pointer pointing to them
+ // when we deallocate them, since otherwise we can't call delete() at all.
+ // This means that we would usually need to create DeadBlocks for all of them.
+ // To work around that, we instead mark them as dead without moving the data
+ // over to a DeadBlock and simply keep the block in a separate DeadAllocations
+ // list.
+ if (B->hasPointers()) {
+ B->AccessFlags |= Block::DeadFlag;
+ DeadAllocations.push_back(std::move(*AllocIt));
+ Site.Allocations.erase(AllocIt);
+
+ if (Site.size() == 0)
+ AllocationSites.erase(It);
+ return true;
+ }
- if (Site.size() == 0)
+ // Get rid of the allocation altogether.
+ Site.Allocations.erase(AllocIt);
+ if (Site.empty())
AllocationSites.erase(It);
return true;
diff --git a/clang/lib/AST/ByteCode/DynamicAllocator.h b/clang/lib/AST/ByteCode/DynamicAllocator.h
index cff09bf..31d0e58 100644
--- a/clang/lib/AST/ByteCode/DynamicAllocator.h
+++ b/clang/lib/AST/ByteCode/DynamicAllocator.h
@@ -43,6 +43,7 @@ private:
std::unique_ptr<std::byte[]> Memory;
Allocation(std::unique_ptr<std::byte[]> Memory)
: Memory(std::move(Memory)) {}
+ Block *block() const { return reinterpret_cast<Block *>(Memory.get()); }
};
struct AllocationSite {
@@ -55,6 +56,7 @@ private:
}
size_t size() const { return Allocations.size(); }
+ bool empty() const { return Allocations.empty(); }
};
public:
@@ -65,8 +67,6 @@ public:
void cleanup();
- unsigned getNumAllocations() const { return AllocationSites.size(); }
-
/// Allocate ONE element of the given descriptor.
Block *allocate(const Descriptor *D, unsigned EvalID, Form AllocForm);
/// Allocate \p NumElements primitive elements of the given type.
@@ -96,8 +96,13 @@ public:
return llvm::make_range(AllocationSites.begin(), AllocationSites.end());
}
+ bool hasAllocations() const { return !AllocationSites.empty(); }
+
private:
llvm::DenseMap<const Expr *, AllocationSite> AllocationSites;
+ // Allocations that have already been deallocated but had pointers
+ // to them.
+ llvm::SmallVector<Allocation> DeadAllocations;
using PoolAllocTy = llvm::BumpPtrAllocator;
PoolAllocTy DescAllocator;
diff --git a/clang/lib/AST/ByteCode/EvalEmitter.cpp b/clang/lib/AST/ByteCode/EvalEmitter.cpp
index 976b7c0..68f46c1 100644
--- a/clang/lib/AST/ByteCode/EvalEmitter.cpp
+++ b/clang/lib/AST/ByteCode/EvalEmitter.cpp
@@ -98,10 +98,7 @@ bool EvalEmitter::interpretCall(const FunctionDecl *FD, const Expr *E) {
this->Params.insert({PD, {0, false}});
}
- if (!this->visit(E))
- return false;
- PrimType T = Ctx.classify(E).value_or(PT_Ptr);
- return this->emitPop(T, E);
+ return this->visitExpr(E, /*DestroyToplevelScope=*/false);
}
void EvalEmitter::emitLabel(LabelTy Label) { CurrentLabel = Label; }
@@ -292,7 +289,7 @@ bool EvalEmitter::emitGetLocal(uint32_t I, const SourceInfo &Info) {
Block *B = getLocal(I);
- if (!CheckLocalLoad(S, OpPC, Pointer(B)))
+ if (!CheckLocalLoad(S, OpPC, B))
return false;
S.Stk.push<T>(*reinterpret_cast<T *>(B->data()));
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index eb4e480..73507d2 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -211,25 +211,26 @@ static void diagnoseNonConstVariable(InterpState &S, CodePtr OpPC,
S.Note(VD->getLocation(), diag::note_declared_at);
}
-static bool CheckTemporary(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
+static bool CheckTemporary(InterpState &S, CodePtr OpPC, const Block *B,
AccessKinds AK) {
- if (auto ID = Ptr.getDeclID()) {
- if (!Ptr.isStaticTemporary())
+ if (B->getDeclID()) {
+ if (!(B->isStatic() && B->isTemporary()))
return true;
const auto *MTE = dyn_cast_if_present<MaterializeTemporaryExpr>(
- Ptr.getDeclDesc()->asExpr());
+ B->getDescriptor()->asExpr());
if (!MTE)
return true;
// FIXME(perf): Since we do this check on every Load from a static
// temporary, it might make sense to cache the value of the
// isUsableInConstantExpressions call.
- if (!MTE->isUsableInConstantExpressions(S.getASTContext()) &&
- Ptr.block()->getEvalID() != S.Ctx.getEvalID()) {
+ if (B->getEvalID() != S.Ctx.getEvalID() &&
+ !MTE->isUsableInConstantExpressions(S.getASTContext())) {
const SourceInfo &E = S.Current->getSource(OpPC);
S.FFDiag(E, diag::note_constexpr_access_static_temporary, 1) << AK;
- S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
+ S.Note(B->getDescriptor()->getLocation(),
+ diag::note_constexpr_temporary_here);
return false;
}
}
@@ -517,7 +518,7 @@ bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
AccessKinds AK) {
- if (!Ptr.isOnePastEnd())
+ if (!Ptr.isOnePastEnd() && !Ptr.isZeroSizeArray())
return true;
if (S.getLangOpts().CPlusPlus) {
const SourceInfo &Loc = S.Current->getSource(OpPC);
@@ -658,17 +659,19 @@ static bool CheckVolatile(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
return false;
}
-bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
- AccessKinds AK) {
+bool DiagnoseUninitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
+ AccessKinds AK) {
assert(Ptr.isLive());
+ assert(!Ptr.isInitialized());
+ return DiagnoseUninitialized(S, OpPC, Ptr.isExtern(), Ptr.getDeclDesc(), AK);
+}
- if (Ptr.isInitialized())
- return true;
-
- if (Ptr.isExtern() && S.checkingPotentialConstantExpression())
+bool DiagnoseUninitialized(InterpState &S, CodePtr OpPC, bool Extern,
+ const Descriptor *Desc, AccessKinds AK) {
+ if (Extern && S.checkingPotentialConstantExpression())
return false;
- if (const auto *VD = Ptr.getDeclDesc()->asVarDecl();
+ if (const auto *VD = Desc->asVarDecl();
VD && (VD->isConstexpr() || VD->hasGlobalStorage())) {
if (VD == S.EvaluatingDecl &&
@@ -703,9 +706,9 @@ bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
return false;
}
-static bool CheckLifetime(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
+static bool CheckLifetime(InterpState &S, CodePtr OpPC, Lifetime LT,
AccessKinds AK) {
- if (Ptr.getLifetime() == Lifetime::Started)
+ if (LT == Lifetime::Started)
return true;
if (!S.checkingPotentialConstantExpression()) {
@@ -715,11 +718,11 @@ static bool CheckLifetime(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
return false;
}
-static bool CheckWeak(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
- if (!Ptr.isWeak())
+static bool CheckWeak(InterpState &S, CodePtr OpPC, const Block *B) {
+ if (!B->isWeak())
return true;
- const auto *VD = Ptr.getDeclDesc()->asVarDecl();
+ const auto *VD = B->getDescriptor()->asVarDecl();
assert(VD);
S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_var_init_weak)
<< VD;
@@ -732,57 +735,100 @@ static bool CheckWeak(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
// ones removed that are impossible on primitive global values.
// For example, since those can't be members of structs, they also can't
// be mutable.
-bool CheckGlobalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
- if (!CheckExtern(S, OpPC, Ptr))
- return false;
- if (!CheckConstant(S, OpPC, Ptr))
- return false;
- if (!CheckDummy(S, OpPC, Ptr, AK_Read))
- return false;
- if (!CheckInitialized(S, OpPC, Ptr, AK_Read))
- return false;
- if (!CheckTemporary(S, OpPC, Ptr, AK_Read))
+bool CheckGlobalLoad(InterpState &S, CodePtr OpPC, const Block *B) {
+ const auto &Desc =
+ *reinterpret_cast<const GlobalInlineDescriptor *>(B->rawData());
+ if (!B->isAccessible()) {
+ if (!CheckExtern(S, OpPC, Pointer(const_cast<Block *>(B))))
+ return false;
+ if (!CheckDummy(S, OpPC, B, AK_Read))
+ return false;
+ return CheckWeak(S, OpPC, B);
+ }
+
+ if (!CheckConstant(S, OpPC, B->getDescriptor()))
return false;
- if (!CheckWeak(S, OpPC, Ptr))
+ if (Desc.InitState != GlobalInitState::Initialized)
+ return DiagnoseUninitialized(S, OpPC, B->isExtern(), B->getDescriptor(),
+ AK_Read);
+ if (!CheckTemporary(S, OpPC, B, AK_Read))
return false;
- if (!CheckVolatile(S, OpPC, Ptr, AK_Read))
+ if (B->getDescriptor()->IsVolatile) {
+ if (!S.getLangOpts().CPlusPlus)
+ return Invalid(S, OpPC);
+
+ const ValueDecl *D = B->getDescriptor()->asValueDecl();
+ S.FFDiag(S.Current->getLocation(OpPC),
+ diag::note_constexpr_access_volatile_obj, 1)
+ << AK_Read << 1 << D;
+ S.Note(D->getLocation(), diag::note_constexpr_volatile_here) << 1;
return false;
+ }
return true;
}
// Similarly, for local loads.
-bool CheckLocalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
- if (!CheckLifetime(S, OpPC, Ptr, AK_Read))
- return false;
- if (!CheckInitialized(S, OpPC, Ptr, AK_Read))
- return false;
- if (!CheckVolatile(S, OpPC, Ptr, AK_Read))
+bool CheckLocalLoad(InterpState &S, CodePtr OpPC, const Block *B) {
+ assert(!B->isExtern());
+ const auto &Desc = *reinterpret_cast<const InlineDescriptor *>(B->rawData());
+ if (!CheckLifetime(S, OpPC, Desc.LifeState, AK_Read))
+ return false;
+ if (!Desc.IsInitialized)
+ return DiagnoseUninitialized(S, OpPC, /*Extern=*/false, B->getDescriptor(),
+ AK_Read);
+ if (B->getDescriptor()->IsVolatile) {
+ if (!S.getLangOpts().CPlusPlus)
+ return Invalid(S, OpPC);
+
+ const ValueDecl *D = B->getDescriptor()->asValueDecl();
+ S.FFDiag(S.Current->getLocation(OpPC),
+ diag::note_constexpr_access_volatile_obj, 1)
+ << AK_Read << 1 << D;
+ S.Note(D->getLocation(), diag::note_constexpr_volatile_here) << 1;
return false;
+ }
return true;
}
bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
AccessKinds AK) {
- if (!CheckLive(S, OpPC, Ptr, AK))
- return false;
- if (!CheckExtern(S, OpPC, Ptr))
+ if (!Ptr.isBlockPointer()) {
+ if (Ptr.isZero()) {
+ const auto &Src = S.Current->getSource(OpPC);
+
+ if (Ptr.isField())
+ S.FFDiag(Src, diag::note_constexpr_null_subobject) << CSK_Field;
+ else
+ S.FFDiag(Src, diag::note_constexpr_access_null) << AK;
+ }
return false;
+ }
+
+ // Block pointers are the only ones we can actually read from.
+ if (!Ptr.block()->isAccessible()) {
+ if (!CheckLive(S, OpPC, Ptr, AK))
+ return false;
+ if (!CheckExtern(S, OpPC, Ptr))
+ return false;
+ if (!CheckDummy(S, OpPC, Ptr.block(), AK))
+ return false;
+ if (!CheckWeak(S, OpPC, Ptr.block()))
+ return false;
+ }
+
if (!CheckConstant(S, OpPC, Ptr))
return false;
- if (!CheckDummy(S, OpPC, Ptr, AK))
- return false;
if (!CheckRange(S, OpPC, Ptr, AK))
return false;
if (!CheckActive(S, OpPC, Ptr, AK))
return false;
- if (!CheckLifetime(S, OpPC, Ptr, AK))
- return false;
- if (!CheckInitialized(S, OpPC, Ptr, AK))
- return false;
- if (!CheckTemporary(S, OpPC, Ptr, AK))
+ if (!CheckLifetime(S, OpPC, Ptr.getLifetime(), AK))
return false;
- if (!CheckWeak(S, OpPC, Ptr))
+ if (!Ptr.isInitialized())
+ return DiagnoseUninitialized(S, OpPC, Ptr, AK);
+ if (!CheckTemporary(S, OpPC, Ptr.block(), AK))
return false;
+
if (!CheckMutable(S, OpPC, Ptr))
return false;
if (!CheckVolatile(S, OpPC, Ptr, AK))
@@ -793,26 +839,39 @@ bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
/// This is not used by any of the opcodes directly. It's used by
/// EvalEmitter to do the final lvalue-to-rvalue conversion.
bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
- if (!CheckLive(S, OpPC, Ptr, AK_Read))
+ if (!Ptr.isBlockPointer()) {
+ if (Ptr.isZero()) {
+ const auto &Src = S.Current->getSource(OpPC);
+
+ if (Ptr.isField())
+ S.FFDiag(Src, diag::note_constexpr_null_subobject) << CSK_Field;
+ else
+ S.FFDiag(Src, diag::note_constexpr_access_null) << AK_Read;
+ }
return false;
+ }
+
+ assert(Ptr.isBlockPointer());
+ if (!Ptr.block()->isAccessible()) {
+ if (!CheckLive(S, OpPC, Ptr, AK_Read))
+ return false;
+ if (!CheckExtern(S, OpPC, Ptr))
+ return false;
+ if (!CheckDummy(S, OpPC, Ptr.block(), AK_Read))
+ return false;
+ return CheckWeak(S, OpPC, Ptr.block());
+ }
+
if (!CheckConstant(S, OpPC, Ptr))
return false;
- if (!CheckDummy(S, OpPC, Ptr, AK_Read))
- return false;
- if (!CheckExtern(S, OpPC, Ptr))
- return false;
- if (!CheckRange(S, OpPC, Ptr, AK_Read))
- return false;
if (!CheckActive(S, OpPC, Ptr, AK_Read))
return false;
- if (!CheckLifetime(S, OpPC, Ptr, AK_Read))
+ if (!CheckLifetime(S, OpPC, Ptr.getLifetime(), AK_Read))
return false;
- if (!CheckInitialized(S, OpPC, Ptr, AK_Read))
- return false;
- if (!CheckTemporary(S, OpPC, Ptr, AK_Read))
- return false;
- if (!CheckWeak(S, OpPC, Ptr))
+ if (!Ptr.isInitialized())
+ return DiagnoseUninitialized(S, OpPC, Ptr, AK_Read);
+ if (!CheckTemporary(S, OpPC, Ptr.block(), AK_Read))
return false;
if (!CheckMutable(S, OpPC, Ptr))
return false;
@@ -820,11 +879,15 @@ bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
}
bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
- if (!CheckLive(S, OpPC, Ptr, AK_Assign))
- return false;
- if (!CheckDummy(S, OpPC, Ptr, AK_Assign))
+ if (!Ptr.isBlockPointer())
return false;
- if (!CheckLifetime(S, OpPC, Ptr, AK_Assign))
+
+ if (!Ptr.block()->isAccessible()) {
+ if (!CheckLive(S, OpPC, Ptr, AK_Assign))
+ return false;
+ return CheckDummy(S, OpPC, Ptr.block(), AK_Assign);
+ }
+ if (!CheckLifetime(S, OpPC, Ptr.getLifetime(), AK_Assign))
return false;
if (!CheckExtern(S, OpPC, Ptr))
return false;
@@ -1098,13 +1161,11 @@ bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR) {
return diagnoseUnknownDecl(S, OpPC, D);
}
-bool CheckDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
- AccessKinds AK) {
- if (!Ptr.isDummy())
+bool CheckDummy(InterpState &S, CodePtr OpPC, const Block *B, AccessKinds AK) {
+ if (!B->isDummy())
return true;
- const Descriptor *Desc = Ptr.getDeclDesc();
- const ValueDecl *D = Desc->asValueDecl();
+ const ValueDecl *D = B->getDescriptor()->asValueDecl();
if (!D)
return false;
@@ -1426,7 +1487,7 @@ static bool checkConstructor(InterpState &S, CodePtr OpPC, const Function *Func,
bool CheckDestructor(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
if (!CheckLive(S, OpPC, Ptr, AK_Destroy))
return false;
- if (!CheckTemporary(S, OpPC, Ptr, AK_Destroy))
+ if (!CheckTemporary(S, OpPC, Ptr.block(), AK_Destroy))
return false;
if (!CheckRange(S, OpPC, Ptr, AK_Destroy))
return false;
@@ -1620,8 +1681,17 @@ bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func,
const auto *StaticDecl = cast<CXXRecordDecl>(Func->getParentDecl());
const auto *InitialFunction = cast<CXXMethodDecl>(Callee);
- const CXXMethodDecl *Overrider = S.getContext().getOverridingFunction(
- DynamicDecl, StaticDecl, InitialFunction);
+ const CXXMethodDecl *Overrider;
+
+ if (StaticDecl != DynamicDecl) {
+ if (!DynamicDecl->isDerivedFrom(StaticDecl))
+ return false;
+ Overrider = S.getContext().getOverridingFunction(DynamicDecl, StaticDecl,
+ InitialFunction);
+
+ } else {
+ Overrider = InitialFunction;
+ }
if (Overrider != InitialFunction) {
// DR1872: An instantiated virtual constexpr function can't be called in a
@@ -1749,7 +1819,7 @@ static void startLifetimeRecurse(const Pointer &Ptr) {
bool StartLifetime(InterpState &S, CodePtr OpPC) {
const auto &Ptr = S.Stk.peek<Pointer>();
- if (!CheckDummy(S, OpPC, Ptr, AK_Destroy))
+ if (Ptr.isBlockPointer() && !CheckDummy(S, OpPC, Ptr.block(), AK_Destroy))
return false;
startLifetimeRecurse(Ptr.narrow());
return true;
@@ -1780,7 +1850,7 @@ static void endLifetimeRecurse(const Pointer &Ptr) {
/// Ends the lifetime of the peek'd pointer.
bool EndLifetime(InterpState &S, CodePtr OpPC) {
const auto &Ptr = S.Stk.peek<Pointer>();
- if (!CheckDummy(S, OpPC, Ptr, AK_Destroy))
+ if (Ptr.isBlockPointer() && !CheckDummy(S, OpPC, Ptr.block(), AK_Destroy))
return false;
endLifetimeRecurse(Ptr.narrow());
return true;
@@ -1789,7 +1859,7 @@ bool EndLifetime(InterpState &S, CodePtr OpPC) {
/// Ends the lifetime of the pop'd pointer.
bool EndLifetimePop(InterpState &S, CodePtr OpPC) {
const auto &Ptr = S.Stk.pop<Pointer>();
- if (!CheckDummy(S, OpPC, Ptr, AK_Destroy))
+ if (Ptr.isBlockPointer() && !CheckDummy(S, OpPC, Ptr.block(), AK_Destroy))
return false;
endLifetimeRecurse(Ptr.narrow());
return true;
@@ -1802,26 +1872,32 @@ bool CheckNewTypeMismatch(InterpState &S, CodePtr OpPC, const Expr *E,
if (Ptr.inUnion() && Ptr.getBase().getRecord()->isUnion())
Ptr.activate();
+ if (!Ptr.isBlockPointer())
+ return false;
+
// Similar to CheckStore(), but with the additional CheckTemporary() call and
// the AccessKinds are different.
- if (!CheckTemporary(S, OpPC, Ptr, AK_Construct))
- return false;
- if (!CheckLive(S, OpPC, Ptr, AK_Construct))
- return false;
- if (!CheckDummy(S, OpPC, Ptr, AK_Construct))
+
+ if (!Ptr.block()->isAccessible()) {
+ if (!CheckExtern(S, OpPC, Ptr))
+ return false;
+ if (!CheckLive(S, OpPC, Ptr, AK_Construct))
+ return false;
+ return CheckDummy(S, OpPC, Ptr.block(), AK_Construct);
+ }
+ if (!CheckTemporary(S, OpPC, Ptr.block(), AK_Construct))
return false;
// CheckLifetime for this and all base pointers.
for (Pointer P = Ptr;;) {
- if (!CheckLifetime(S, OpPC, P, AK_Construct))
+ if (!CheckLifetime(S, OpPC, P.getLifetime(), AK_Construct))
return false;
if (P.isRoot())
break;
P = P.getBase();
}
- if (!CheckExtern(S, OpPC, Ptr))
- return false;
+
if (!CheckRange(S, OpPC, Ptr, AK_Construct))
return false;
if (!CheckGlobal(S, OpPC, Ptr))
@@ -2011,7 +2087,7 @@ bool GetTypeidPtr(InterpState &S, CodePtr OpPC, const Type *TypeInfoType) {
return false;
// Pick the most-derived type.
- const Type *T = P.getDeclPtr().getType().getTypePtr();
+ CanQualType T = P.getDeclPtr().getType()->getCanonicalTypeUnqualified();
// ... unless we're currently constructing this object.
// FIXME: We have a similar check to this in more places.
if (S.Current->getFunction()) {
@@ -2019,14 +2095,14 @@ bool GetTypeidPtr(InterpState &S, CodePtr OpPC, const Type *TypeInfoType) {
if (const Function *Func = Frame->getFunction();
Func && (Func->isConstructor() || Func->isDestructor()) &&
P.block() == Frame->getThis().block()) {
- T = Func->getParentDecl()->getTypeForDecl();
+ T = S.getContext().getASTContext().getCanonicalTagType(
+ Func->getParentDecl());
break;
}
}
}
- S.Stk.push<Pointer>(T->getCanonicalTypeUnqualified().getTypePtr(),
- TypeInfoType);
+ S.Stk.push<Pointer>(T->getTypePtr(), TypeInfoType);
return true;
}
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 8a28106..75901e5 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -51,8 +51,7 @@ bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
AccessKinds AK);
/// Checks if a pointer is a dummy pointer.
-bool CheckDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
- AccessKinds AK);
+bool CheckDummy(InterpState &S, CodePtr OpPC, const Block *B, AccessKinds AK);
/// Checks if a pointer is null.
bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
@@ -89,11 +88,14 @@ bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
AccessKinds AK = AK_Read);
bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
-bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
- AccessKinds AK);
+bool DiagnoseUninitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
+ AccessKinds AK);
+bool DiagnoseUninitialized(InterpState &S, CodePtr OpPC, bool Extern,
+ const Descriptor *Desc, AccessKinds AK);
+
/// Checks a direct load of a primitive value from a global or local variable.
-bool CheckGlobalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
-bool CheckLocalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
+bool CheckGlobalLoad(InterpState &S, CodePtr OpPC, const Block *B);
+bool CheckLocalLoad(InterpState &S, CodePtr OpPC, const Block *B);
/// Checks if a value can be stored in a block.
bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
@@ -1351,10 +1353,10 @@ inline bool ConstFloat(InterpState &S, CodePtr OpPC, const Floating &F) {
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool GetLocal(InterpState &S, CodePtr OpPC, uint32_t I) {
- const Pointer &Ptr = S.Current->getLocalPointer(I);
- if (!CheckLocalLoad(S, OpPC, Ptr))
+ const Block *B = S.Current->getLocalBlock(I);
+ if (!CheckLocalLoad(S, OpPC, B))
return false;
- S.Stk.push<T>(Ptr.deref<T>());
+ S.Stk.push<T>(B->deref<T>());
return true;
}
@@ -1465,22 +1467,26 @@ bool SetThisField(InterpState &S, CodePtr OpPC, uint32_t I) {
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool GetGlobal(InterpState &S, CodePtr OpPC, uint32_t I) {
- const Pointer &Ptr = S.P.getPtrGlobal(I);
+ const Block *B = S.P.getGlobal(I);
- if (!CheckGlobalLoad(S, OpPC, Ptr))
+ if (!CheckGlobalLoad(S, OpPC, B))
return false;
- S.Stk.push<T>(Ptr.deref<T>());
+ S.Stk.push<T>(B->deref<T>());
return true;
}
/// Same as GetGlobal, but without the checks.
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool GetGlobalUnchecked(InterpState &S, CodePtr OpPC, uint32_t I) {
- const Pointer &Ptr = S.P.getPtrGlobal(I);
- if (!CheckInitialized(S, OpPC, Ptr, AK_Read))
- return false;
- S.Stk.push<T>(Ptr.deref<T>());
+ const Block *B = S.P.getGlobal(I);
+ const auto &Desc =
+ *reinterpret_cast<const GlobalInlineDescriptor *>(B->rawData());
+ if (Desc.InitState != GlobalInitState::Initialized)
+ return DiagnoseUninitialized(S, OpPC, B->isExtern(), B->getDescriptor(),
+ AK_Read);
+
+ S.Stk.push<T>(B->deref<T>());
return true;
}
@@ -1764,10 +1770,7 @@ inline bool GetPtrDerivedPop(InterpState &S, CodePtr OpPC, uint32_t Off,
const Record *TargetRecord = Ptr.atFieldSub(Off).getRecord();
assert(TargetRecord);
- if (TargetRecord->getDecl()
- ->getTypeForDecl()
- ->getAsCXXRecordDecl()
- ->getCanonicalDecl() !=
+ if (TargetRecord->getDecl()->getCanonicalDecl() !=
TargetType->getAsCXXRecordDecl()->getCanonicalDecl()) {
QualType MostDerivedType = Ptr.getDeclDesc()->getType();
S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_invalid_downcast)
@@ -2351,8 +2354,8 @@ static inline bool IncDecPtrHelper(InterpState &S, CodePtr OpPC,
static inline bool IncPtr(InterpState &S, CodePtr OpPC) {
const Pointer &Ptr = S.Stk.pop<Pointer>();
- if (!CheckInitialized(S, OpPC, Ptr, AK_Increment))
- return false;
+ if (!Ptr.isInitialized())
+ return DiagnoseUninitialized(S, OpPC, Ptr, AK_Increment);
return IncDecPtrHelper<ArithOp::Add>(S, OpPC, Ptr);
}
@@ -2360,8 +2363,8 @@ static inline bool IncPtr(InterpState &S, CodePtr OpPC) {
static inline bool DecPtr(InterpState &S, CodePtr OpPC) {
const Pointer &Ptr = S.Stk.pop<Pointer>();
- if (!CheckInitialized(S, OpPC, Ptr, AK_Decrement))
- return false;
+ if (!Ptr.isInitialized())
+ return DiagnoseUninitialized(S, OpPC, Ptr, AK_Decrement);
return IncDecPtrHelper<ArithOp::Sub>(S, OpPC, Ptr);
}
@@ -3195,6 +3198,9 @@ inline bool GetMemberPtr(InterpState &S, CodePtr OpPC, const ValueDecl *D) {
inline bool GetMemberPtrBase(InterpState &S, CodePtr OpPC) {
const auto &MP = S.Stk.pop<MemberPointer>();
+ if (!MP.isBaseCastPossible())
+ return false;
+
S.Stk.push<Pointer>(MP.getBase());
return true;
}
diff --git a/clang/lib/AST/ByteCode/InterpBlock.cpp b/clang/lib/AST/ByteCode/InterpBlock.cpp
index 963b54e..69221d8 100644
--- a/clang/lib/AST/ByteCode/InterpBlock.cpp
+++ b/clang/lib/AST/ByteCode/InterpBlock.cpp
@@ -64,7 +64,7 @@ void Block::removePointer(Pointer *P) {
}
void Block::cleanup() {
- if (Pointers == nullptr && IsDead)
+ if (Pointers == nullptr && !IsDynamic && isDead())
(reinterpret_cast<DeadBlock *>(this + 1) - 1)->free();
}
@@ -113,8 +113,8 @@ bool Block::hasPointer(const Pointer *P) const {
#endif
DeadBlock::DeadBlock(DeadBlock *&Root, Block *Blk)
- : Root(Root), B(~0u, Blk->Desc, Blk->IsStatic, Blk->IsExtern, Blk->IsWeak,
- /*isDead=*/true) {
+ : Root(Root), B(~0u, Blk->Desc, Blk->isExtern(), Blk->IsStatic,
+ Blk->isWeak(), Blk->isDummy(), /*IsDead=*/true) {
// Add the block to the chain of dead blocks.
if (Root)
Root->Prev = this;
@@ -133,8 +133,7 @@ DeadBlock::DeadBlock(DeadBlock *&Root, Block *Blk)
}
void DeadBlock::free() {
- if (B.IsInitialized)
- B.invokeDtor();
+ assert(!B.isInitialized());
if (Prev)
Prev->Next = Next;
diff --git a/clang/lib/AST/ByteCode/InterpBlock.h b/clang/lib/AST/ByteCode/InterpBlock.h
index 5162223..7ded1e8 100644
--- a/clang/lib/AST/ByteCode/InterpBlock.h
+++ b/clang/lib/AST/ByteCode/InterpBlock.h
@@ -42,21 +42,32 @@ enum PrimType : unsigned;
/// the data size and the metadata size.
///
class Block final {
+private:
+ static constexpr uint8_t ExternFlag = 1 << 0;
+ static constexpr uint8_t DeadFlag = 1 << 1;
+ static constexpr uint8_t WeakFlag = 1 << 2;
+ static constexpr uint8_t DummyFlag = 1 << 3;
+
public:
/// Creates a new block.
Block(unsigned EvalID, const std::optional<unsigned> &DeclID,
const Descriptor *Desc, bool IsStatic = false, bool IsExtern = false,
- bool IsWeak = false)
- : EvalID(EvalID), DeclID(DeclID), IsStatic(IsStatic), IsExtern(IsExtern),
- IsDynamic(false), IsWeak(IsWeak), Desc(Desc) {
+ bool IsWeak = false, bool IsDummy = false)
+ : Desc(Desc), DeclID(DeclID), EvalID(EvalID), IsStatic(IsStatic) {
assert(Desc);
+ AccessFlags |= (ExternFlag * IsExtern);
+ AccessFlags |= (WeakFlag * IsWeak);
+ AccessFlags |= (DummyFlag * IsDummy);
}
Block(unsigned EvalID, const Descriptor *Desc, bool IsStatic = false,
- bool IsExtern = false, bool IsWeak = false)
- : EvalID(EvalID), DeclID((unsigned)-1), IsStatic(IsStatic),
- IsExtern(IsExtern), IsDynamic(false), IsWeak(IsWeak), Desc(Desc) {
+ bool IsExtern = false, bool IsWeak = false, bool IsDummy = false)
+ : Desc(Desc), DeclID((unsigned)-1), EvalID(EvalID), IsStatic(IsStatic),
+ IsDynamic(false) {
assert(Desc);
+ AccessFlags |= (ExternFlag * IsExtern);
+ AccessFlags |= (WeakFlag * IsWeak);
+ AccessFlags |= (DummyFlag * IsDummy);
}
/// Returns the block's descriptor.
@@ -64,13 +75,15 @@ public:
/// Checks if the block has any live pointers.
bool hasPointers() const { return Pointers; }
/// Checks if the block is extern.
- bool isExtern() const { return IsExtern; }
+ bool isExtern() const { return AccessFlags & ExternFlag; }
/// Checks if the block has static storage duration.
bool isStatic() const { return IsStatic; }
/// Checks if the block is temporary.
bool isTemporary() const { return Desc->IsTemporary; }
- bool isWeak() const { return IsWeak; }
+ bool isWeak() const { return AccessFlags & WeakFlag; }
bool isDynamic() const { return IsDynamic; }
+ bool isDummy() const { return AccessFlags & DummyFlag; }
+ bool isDead() const { return AccessFlags & DeadFlag; }
/// Returns the size of the block.
unsigned getSize() const { return Desc->getAllocSize(); }
/// Returns the declaration ID.
@@ -103,6 +116,10 @@ public:
return reinterpret_cast<const std::byte *>(this) + sizeof(Block);
}
+ template <typename T> T deref() const {
+ return *reinterpret_cast<const T *>(data());
+ }
+
/// Invokes the constructor.
void invokeCtor() {
assert(!IsInitialized);
@@ -126,6 +143,8 @@ public:
void dump() const { dump(llvm::errs()); }
void dump(llvm::raw_ostream &OS) const;
+ bool isAccessible() const { return AccessFlags == 0; }
+
private:
friend class Pointer;
friend class DeadBlock;
@@ -133,10 +152,13 @@ private:
friend class DynamicAllocator;
Block(unsigned EvalID, const Descriptor *Desc, bool IsExtern, bool IsStatic,
- bool IsWeak, bool IsDead)
- : EvalID(EvalID), IsStatic(IsStatic), IsExtern(IsExtern), IsDead(true),
- IsDynamic(false), IsWeak(IsWeak), Desc(Desc) {
+ bool IsWeak, bool IsDummy, bool IsDead)
+ : Desc(Desc), EvalID(EvalID), IsStatic(IsStatic) {
assert(Desc);
+ AccessFlags |= (ExternFlag * IsExtern);
+ AccessFlags |= (DeadFlag * IsDead);
+ AccessFlags |= (WeakFlag * IsWeak);
+ AccessFlags |= (DummyFlag * IsDummy);
}
/// Deletes a dead block at the end of its lifetime.
@@ -150,27 +172,23 @@ private:
bool hasPointer(const Pointer *P) const;
#endif
- const unsigned EvalID = ~0u;
+ /// Pointer to the stack slot descriptor.
+ const Descriptor *Desc;
/// Start of the chain of pointers.
Pointer *Pointers = nullptr;
/// Unique identifier of the declaration.
std::optional<unsigned> DeclID;
+ const unsigned EvalID = ~0u;
/// Flag indicating if the block has static storage duration.
bool IsStatic = false;
- /// Flag indicating if the block is an extern.
- bool IsExtern = false;
- /// Flag indicating if the pointer is dead. This is only ever
- /// set once, when converting the Block to a DeadBlock.
- bool IsDead = false;
/// Flag indicating if the block contents have been initialized
/// via invokeCtor.
bool IsInitialized = false;
/// Flag indicating if this block has been allocated via dynamic
/// memory allocation (e.g. malloc).
bool IsDynamic = false;
- bool IsWeak = false;
- /// Pointer to the stack slot descriptor.
- const Descriptor *Desc;
+ /// AccessFlags containing IsExtern, IsDead, IsWeak, and IsDummy bits.
+ uint8_t AccessFlags = 0;
};
/// Descriptor for a dead block.
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index f908d02..14f6929 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -276,7 +276,7 @@ static bool interp__builtin_strlen(InterpState &S, CodePtr OpPC,
if (!CheckLive(S, OpPC, StrPtr, AK_Read))
return false;
- if (!CheckDummy(S, OpPC, StrPtr, AK_Read))
+ if (!CheckDummy(S, OpPC, StrPtr.block(), AK_Read))
return false;
assert(StrPtr.getFieldDesc()->isPrimitiveArray());
@@ -1544,8 +1544,7 @@ static bool interp__builtin_operator_new(InterpState &S, CodePtr OpPC,
// Composite arrays
if (IsArray) {
const Descriptor *Desc =
- S.P.createDescriptor(NewCall, ElemType.getTypePtr(),
- IsArray ? std::nullopt : Descriptor::InlineDescMD);
+ S.P.createDescriptor(NewCall, ElemType.getTypePtr(), std::nullopt);
Block *B =
Allocator.allocate(Desc, NumElems.getZExtValue(), S.Ctx.getEvalID(),
DynamicAllocator::Form::Operator);
@@ -1558,9 +1557,8 @@ static bool interp__builtin_operator_new(InterpState &S, CodePtr OpPC,
QualType AllocType = S.getASTContext().getConstantArrayType(
ElemType, NumElems, nullptr, ArraySizeModifier::Normal, 0);
- const Descriptor *Desc =
- S.P.createDescriptor(NewCall, AllocType.getTypePtr(),
- IsArray ? std::nullopt : Descriptor::InlineDescMD);
+ const Descriptor *Desc = S.P.createDescriptor(NewCall, AllocType.getTypePtr(),
+ Descriptor::InlineDescMD);
Block *B = Allocator.allocate(Desc, S.getContext().getEvalID(),
DynamicAllocator::Form::Operator);
assert(B);
@@ -1785,6 +1783,13 @@ static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC,
return false;
QualType DestElemType = getElemType(DestPtr);
+ if (DestElemType->isIncompleteType()) {
+ S.FFDiag(S.Current->getSource(OpPC),
+ diag::note_constexpr_ltor_incomplete_type)
+ << DestElemType;
+ return false;
+ }
+
size_t RemainingDestElems;
if (DestPtr.getFieldDesc()->isArray()) {
RemainingDestElems = DestPtr.isUnknownSizeArray()
@@ -2232,7 +2237,7 @@ static bool interp__builtin_is_within_lifetime(InterpState &S, CodePtr OpPC,
return false;
if (!CheckMutable(S, OpPC, Ptr))
return false;
- if (!CheckDummy(S, OpPC, Ptr, AK_Read))
+ if (!CheckDummy(S, OpPC, Ptr.block(), AK_Read))
return false;
}
@@ -2754,7 +2759,7 @@ bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E,
const RecordType *RT = CurrentType->getAs<RecordType>();
if (!RT)
return false;
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
if (RD->isInvalidDecl())
return false;
const ASTRecordLayout &RL = S.getASTContext().getASTRecordLayout(RD);
@@ -2787,7 +2792,7 @@ bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E,
const RecordType *RT = CurrentType->getAs<RecordType>();
if (!RT)
return false;
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
if (RD->isInvalidDecl())
return false;
const ASTRecordLayout &RL = S.getASTContext().getASTRecordLayout(RD);
@@ -2799,7 +2804,8 @@ bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E,
return false;
// Add the offset to the base.
- Result += RL.getBaseClassOffset(cast<CXXRecordDecl>(BaseRT->getDecl()));
+ Result += RL.getBaseClassOffset(cast<CXXRecordDecl>(
+ BaseRT->getOriginalDecl()->getDefinitionOrSelf()));
break;
}
case OffsetOfNode::Identifier:
diff --git a/clang/lib/AST/ByteCode/InterpFrame.cpp b/clang/lib/AST/ByteCode/InterpFrame.cpp
index 14f99c7..18400b10 100644
--- a/clang/lib/AST/ByteCode/InterpFrame.cpp
+++ b/clang/lib/AST/ByteCode/InterpFrame.cpp
@@ -133,6 +133,11 @@ static bool shouldSkipInBacktrace(const Function *F) {
MD && MD->getParent()->isAnonymousStructOrUnion())
return true;
+ if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(FD);
+ Ctor && Ctor->isDefaulted() && Ctor->isTrivial() &&
+ Ctor->isCopyOrMoveConstructor() && Ctor->inits().empty())
+ return true;
+
return false;
}
@@ -164,7 +169,7 @@ void InterpFrame::describe(llvm::raw_ostream &OS) const {
} else if (const auto *M = dyn_cast<CXXMethodDecl>(F)) {
print(OS, This, S.getASTContext(),
S.getASTContext().getLValueReferenceType(
- S.getASTContext().getRecordType(M->getParent())));
+ S.getASTContext().getCanonicalTagType(M->getParent())));
OS << ".";
}
}
@@ -226,6 +231,10 @@ Pointer InterpFrame::getLocalPointer(unsigned Offset) const {
return Pointer(localBlock(Offset));
}
+Block *InterpFrame::getLocalBlock(unsigned Offset) const {
+ return localBlock(Offset);
+}
+
Pointer InterpFrame::getParamPointer(unsigned Off) {
// Return the block if it was created previously.
if (auto Pt = Params.find(Off); Pt != Params.end())
diff --git a/clang/lib/AST/ByteCode/InterpFrame.h b/clang/lib/AST/ByteCode/InterpFrame.h
index cfebe93..4be5391 100644
--- a/clang/lib/AST/ByteCode/InterpFrame.h
+++ b/clang/lib/AST/ByteCode/InterpFrame.h
@@ -86,6 +86,7 @@ public:
/// Returns a pointer to a local variables.
Pointer getLocalPointer(unsigned Offset) const;
+ Block *getLocalBlock(unsigned Offset) const;
/// Returns the value of an argument.
template <typename T> const T &getParam(unsigned Offset) const {
diff --git a/clang/lib/AST/ByteCode/InterpState.cpp b/clang/lib/AST/ByteCode/InterpState.cpp
index a06b125..b5f0f9a 100644
--- a/clang/lib/AST/ByteCode/InterpState.cpp
+++ b/clang/lib/AST/ByteCode/InterpState.cpp
@@ -76,8 +76,9 @@ bool InterpState::reportOverflow(const Expr *E, const llvm::APSInt &Value) {
void InterpState::deallocate(Block *B) {
assert(B);
- const Descriptor *Desc = B->getDescriptor();
- assert(Desc);
+ assert(!B->isDynamic());
+ assert(!B->isStatic());
+ assert(!B->isDead());
// The block might have a pointer saved in a field in its data
// that points to the block itself. We call the dtor first,
@@ -87,6 +88,7 @@ void InterpState::deallocate(Block *B) {
if (B->IsInitialized)
B->invokeDtor();
+ assert(!B->isInitialized());
if (B->hasPointers()) {
size_t Size = B->getSize();
// Allocate a new block, transferring over pointers.
@@ -95,24 +97,20 @@ void InterpState::deallocate(Block *B) {
auto *D = new (Memory) DeadBlock(DeadBlocks, B);
// Since the block doesn't hold any actual data anymore, we can just
// memcpy() everything over.
- std::memcpy(D->rawData(), B->rawData(), Desc->getAllocSize());
- D->B.IsInitialized = B->IsInitialized;
-
- // We moved the contents over to the DeadBlock.
- B->IsInitialized = false;
+ std::memcpy(D->rawData(), B->rawData(), Size);
+ D->B.IsInitialized = false;
}
}
bool InterpState::maybeDiagnoseDanglingAllocations() {
- bool NoAllocationsLeft = (Alloc.getNumAllocations() == 0);
+ bool NoAllocationsLeft = !Alloc.hasAllocations();
if (!checkingPotentialConstantExpression()) {
- for (const auto &It : Alloc.allocation_sites()) {
- assert(It.second.size() > 0);
+ for (const auto &[Source, Site] : Alloc.allocation_sites()) {
+ assert(!Site.empty());
- const Expr *Source = It.first;
CCEDiag(Source->getExprLoc(), diag::note_constexpr_memory_leak)
- << (It.second.size() - 1) << Source->getSourceRange();
+ << (Site.size() - 1) << Source->getSourceRange();
}
}
// Keep evaluating before C++20, since the CXXNewExpr wasn't valid there
diff --git a/clang/lib/AST/ByteCode/MemberPointer.h b/clang/lib/AST/ByteCode/MemberPointer.h
index b17ce25..8dd75ca 100644
--- a/clang/lib/AST/ByteCode/MemberPointer.h
+++ b/clang/lib/AST/ByteCode/MemberPointer.h
@@ -51,6 +51,12 @@ public:
FunctionPointer toFunctionPointer(const Context &Ctx) const;
+ bool isBaseCastPossible() const {
+ if (PtrOffset < 0)
+ return true;
+ return static_cast<uint64_t>(PtrOffset) <= Base.getByteOffset();
+ }
+
Pointer getBase() const {
if (PtrOffset < 0)
return Base.atField(-PtrOffset);
diff --git a/clang/lib/AST/ByteCode/Pointer.cpp b/clang/lib/AST/ByteCode/Pointer.cpp
index dec2088..4d70ae5 100644
--- a/clang/lib/AST/ByteCode/Pointer.cpp
+++ b/clang/lib/AST/ByteCode/Pointer.cpp
@@ -689,7 +689,7 @@ std::optional<APValue> Pointer::toRValue(const Context &Ctx,
assert(Record && "Missing record descriptor");
bool Ok = true;
- if (RT->getDecl()->isUnion()) {
+ if (RT->getOriginalDecl()->isUnion()) {
const FieldDecl *ActiveField = nullptr;
APValue Value;
for (const auto &F : Record->fields()) {
@@ -728,14 +728,15 @@ std::optional<APValue> Pointer::toRValue(const Context &Ctx,
for (unsigned I = 0; I < NB; ++I) {
const Record::Base *BD = Record->getBase(I);
- QualType BaseTy = Ctx.getASTContext().getRecordType(BD->Decl);
+ QualType BaseTy = Ctx.getASTContext().getCanonicalTagType(BD->Decl);
const Pointer &BP = Ptr.atField(BD->Offset);
Ok &= Composite(BaseTy, BP, R.getStructBase(I));
}
for (unsigned I = 0; I < NV; ++I) {
const Record::Base *VD = Record->getVirtualBase(I);
- QualType VirtBaseTy = Ctx.getASTContext().getRecordType(VD->Decl);
+ QualType VirtBaseTy =
+ Ctx.getASTContext().getCanonicalTagType(VD->Decl);
const Pointer &VP = Ptr.atField(VD->Offset);
Ok &= Composite(VirtBaseTy, VP, R.getStructBase(NB + I));
}
diff --git a/clang/lib/AST/ByteCode/Pointer.h b/clang/lib/AST/ByteCode/Pointer.h
index 5bafc5b..94c83a0 100644
--- a/clang/lib/AST/ByteCode/Pointer.h
+++ b/clang/lib/AST/ByteCode/Pointer.h
@@ -282,7 +282,7 @@ public:
bool isLive() const {
if (!isBlockPointer())
return true;
- return asBlockPointer().Pointee && !asBlockPointer().Pointee->IsDead;
+ return asBlockPointer().Pointee && !asBlockPointer().Pointee->isDead();
}
/// Checks if the item is a field in an object.
bool isField() const {
@@ -568,10 +568,9 @@ public:
if (!isBlockPointer())
return false;
- if (!asBlockPointer().Pointee)
- return false;
-
- return getDeclDesc()->isDummy();
+ if (const Block *Pointee = asBlockPointer().Pointee)
+ return Pointee->isDummy();
+ return false;
}
/// Checks if an object or a subfield is mutable.
diff --git a/clang/lib/AST/ByteCode/Program.cpp b/clang/lib/AST/ByteCode/Program.cpp
index 4daa4ab..2843b32 100644
--- a/clang/lib/AST/ByteCode/Program.cpp
+++ b/clang/lib/AST/ByteCode/Program.cpp
@@ -180,17 +180,15 @@ unsigned Program::getOrCreateDummy(const DeclTy &D) {
Desc = allocateDescriptor(D);
assert(Desc);
- Desc->makeDummy();
-
- assert(Desc->isDummy());
// Allocate a block for storage.
unsigned I = Globals.size();
auto *G = new (Allocator, Desc->getAllocSize())
Global(Ctx.getEvalID(), getCurrentDecl(), Desc, /*IsStatic=*/true,
- /*IsExtern=*/false, IsWeak);
+ /*IsExtern=*/false, IsWeak, /*IsDummy=*/true);
G->block()->invokeCtor();
+ assert(G->block()->isDummy());
Globals.push_back(G);
DummyVariables[D.getOpaqueValue()] = I;
@@ -325,7 +323,7 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) {
const auto *RT = Spec.getType()->getAs<RecordType>();
if (!RT)
return nullptr;
- const RecordDecl *BD = RT->getDecl();
+ const RecordDecl *BD = RT->getOriginalDecl()->getDefinitionOrSelf();
const Record *BR = getOrCreateRecord(BD);
const Descriptor *Desc = GetBaseDesc(BD, BR);
@@ -342,7 +340,7 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) {
if (!RT)
return nullptr;
- const RecordDecl *BD = RT->getDecl();
+ const RecordDecl *BD = RT->getOriginalDecl()->getDefinitionOrSelf();
const Record *BR = getOrCreateRecord(BD);
const Descriptor *Desc = GetBaseDesc(BD, BR);
@@ -399,7 +397,8 @@ Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty,
// Classes and structures.
if (const auto *RT = Ty->getAs<RecordType>()) {
- if (const auto *Record = getOrCreateRecord(RT->getDecl()))
+ if (const auto *Record =
+ getOrCreateRecord(RT->getOriginalDecl()->getDefinitionOrSelf()))
return allocateDescriptor(D, Record, MDSize, IsConst, IsTemporary,
IsMutable, IsVolatile);
return allocateDescriptor(D, MDSize);
diff --git a/clang/lib/AST/ByteCode/Record.cpp b/clang/lib/AST/ByteCode/Record.cpp
index 1d4ac71..a7934cc 100644
--- a/clang/lib/AST/ByteCode/Record.cpp
+++ b/clang/lib/AST/ByteCode/Record.cpp
@@ -51,7 +51,7 @@ const Record::Base *Record::getBase(const RecordDecl *FD) const {
const Record::Base *Record::getBase(QualType T) const {
if (auto *RT = T->getAs<RecordType>()) {
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
return BaseMap.lookup(RD);
}
return nullptr;
diff --git a/clang/lib/AST/CXXInheritance.cpp b/clang/lib/AST/CXXInheritance.cpp
index f037616..e4b77ed 100644
--- a/clang/lib/AST/CXXInheritance.cpp
+++ b/clang/lib/AST/CXXInheritance.cpp
@@ -132,8 +132,8 @@ bool CXXRecordDecl::forallBases(ForallBasesCallback BaseMatches) const {
if (!Ty)
return false;
- CXXRecordDecl *Base =
- cast_if_present<CXXRecordDecl>(Ty->getDecl()->getDefinition());
+ CXXRecordDecl *Base = cast_if_present<CXXRecordDecl>(
+ Ty->getOriginalDecl()->getDefinition());
if (!Base ||
(Base->isDependentContext() &&
!Base->isCurrentInstantiation(Record))) {
@@ -256,7 +256,8 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context,
BaseSpec.getType()->getAs<TemplateSpecializationType>();
if (!TST) {
if (auto *RT = BaseSpec.getType()->getAs<RecordType>())
- BaseRecord = cast<CXXRecordDecl>(RT->getDecl());
+ BaseRecord = cast<CXXRecordDecl>(RT->getOriginalDecl())
+ ->getDefinitionOrSelf();
} else {
TemplateName TN = TST->getTemplateName();
if (auto *TD =
@@ -336,7 +337,8 @@ bool CXXRecordDecl::lookupInBases(BaseMatchesCallback BaseMatches,
CXXRecordDecl *VBase = nullptr;
if (const RecordType *Record = PE.Base->getType()->getAs<RecordType>())
- VBase = cast<CXXRecordDecl>(Record->getDecl());
+ VBase = cast<CXXRecordDecl>(Record->getOriginalDecl())
+ ->getDefinitionOrSelf();
if (!VBase)
break;
@@ -348,7 +350,8 @@ bool CXXRecordDecl::lookupInBases(BaseMatchesCallback BaseMatches,
CXXRecordDecl *HidingClass = nullptr;
if (const RecordType *Record =
HidingP.back().Base->getType()->getAs<RecordType>())
- HidingClass = cast<CXXRecordDecl>(Record->getDecl());
+ HidingClass = cast<CXXRecordDecl>(Record->getOriginalDecl())
+ ->getDefinitionOrSelf();
if (!HidingClass)
break;
@@ -468,7 +471,8 @@ void FinalOverriderCollector::Collect(const CXXRecordDecl *RD,
for (const auto &Base : RD->bases()) {
if (const RecordType *RT = Base.getType()->getAs<RecordType>()) {
- const CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(RT->getDecl());
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(RT->getOriginalDecl())->getDefinitionOrSelf();
if (!BaseDecl->isPolymorphic())
continue;
diff --git a/clang/lib/AST/Comment.cpp b/clang/lib/AST/Comment.cpp
index cd73d27..37e21c3 100644
--- a/clang/lib/AST/Comment.cpp
+++ b/clang/lib/AST/Comment.cpp
@@ -147,8 +147,6 @@ static TypeLoc lookThroughTypedefOrTypeAliasLocs(TypeLoc &SrcTL) {
return BlockPointerTL.getPointeeLoc().getUnqualifiedLoc();
if (MemberPointerTypeLoc MemberPointerTL = TL.getAs<MemberPointerTypeLoc>())
return MemberPointerTL.getPointeeLoc().getUnqualifiedLoc();
- if (ElaboratedTypeLoc ETL = TL.getAs<ElaboratedTypeLoc>())
- return ETL.getNamedTypeLoc();
return TL;
}
diff --git a/clang/lib/AST/CommentParser.cpp b/clang/lib/AST/CommentParser.cpp
index e61846d..2e5821a 100644
--- a/clang/lib/AST/CommentParser.cpp
+++ b/clang/lib/AST/CommentParser.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/CommentParser.h"
+#include "clang/AST/Comment.h"
#include "clang/AST/CommentCommandTraits.h"
#include "clang/AST/CommentSema.h"
#include "clang/Basic/CharInfo.h"
@@ -569,6 +570,8 @@ BlockCommandComment *Parser::parseBlockCommand() {
InlineCommandComment *Parser::parseInlineCommand() {
assert(Tok.is(tok::backslash_command) || Tok.is(tok::at_command));
+ CommandMarkerKind CMK =
+ Tok.is(tok::backslash_command) ? CMK_Backslash : CMK_At;
const CommandInfo *Info = Traits.getCommandInfo(Tok.getCommandID());
const Token CommandTok = Tok;
@@ -580,7 +583,7 @@ InlineCommandComment *Parser::parseInlineCommand() {
InlineCommandComment *IC = S.actOnInlineCommand(
CommandTok.getLocation(), CommandTok.getEndLocation(),
- CommandTok.getCommandID(), Args);
+ CommandTok.getCommandID(), CMK, Args);
if (Args.size() < Info->NumArgs) {
Diag(CommandTok.getEndLocation().getLocWithOffset(1),
diff --git a/clang/lib/AST/CommentSema.cpp b/clang/lib/AST/CommentSema.cpp
index 88520d7..649fba9 100644
--- a/clang/lib/AST/CommentSema.cpp
+++ b/clang/lib/AST/CommentSema.cpp
@@ -363,12 +363,13 @@ void Sema::actOnTParamCommandFinish(TParamCommandComment *Command,
InlineCommandComment *
Sema::actOnInlineCommand(SourceLocation CommandLocBegin,
SourceLocation CommandLocEnd, unsigned CommandID,
+ CommandMarkerKind CommandMarker,
ArrayRef<Comment::Argument> Args) {
StringRef CommandName = Traits.getCommandInfo(CommandID)->Name;
- return new (Allocator)
- InlineCommandComment(CommandLocBegin, CommandLocEnd, CommandID,
- getInlineCommandRenderKind(CommandName), Args);
+ return new (Allocator) InlineCommandComment(
+ CommandLocBegin, CommandLocEnd, CommandID,
+ getInlineCommandRenderKind(CommandName), CommandMarker, Args);
}
InlineContentComment *Sema::actOnUnknownCommand(SourceLocation LocBegin,
@@ -905,17 +906,9 @@ bool Sema::isClassOrStructOrTagTypedefDecl() {
if (isClassOrStructDeclImpl(ThisDeclInfo->CurrentDecl))
return true;
- if (auto *ThisTypedefDecl = dyn_cast<TypedefDecl>(ThisDeclInfo->CurrentDecl)) {
- auto UnderlyingType = ThisTypedefDecl->getUnderlyingType();
- if (auto ThisElaboratedType = dyn_cast<ElaboratedType>(UnderlyingType)) {
- auto DesugaredType = ThisElaboratedType->desugar();
- if (auto *DesugaredTypePtr = DesugaredType.getTypePtrOrNull()) {
- if (auto *ThisRecordType = dyn_cast<RecordType>(DesugaredTypePtr)) {
- return isClassOrStructDeclImpl(ThisRecordType->getAsRecordDecl());
- }
- }
- }
- }
+ if (auto *ThisTypedefDecl = dyn_cast<TypedefDecl>(ThisDeclInfo->CurrentDecl))
+ if (auto *D = ThisTypedefDecl->getUnderlyingType()->getAsRecordDecl())
+ return isClassOrStructDeclImpl(D);
return false;
}
diff --git a/clang/lib/AST/ComparisonCategories.cpp b/clang/lib/AST/ComparisonCategories.cpp
index 2824410..0c7a7f4 100644
--- a/clang/lib/AST/ComparisonCategories.cpp
+++ b/clang/lib/AST/ComparisonCategories.cpp
@@ -166,7 +166,7 @@ const ComparisonCategoryInfo &ComparisonCategories::getInfoForType(QualType Ty)
QualType ComparisonCategoryInfo::getType() const {
assert(Record);
- return QualType(Record->getTypeForDecl(), 0);
+ return Record->getASTContext().getCanonicalTagType(Record);
}
StringRef ComparisonCategories::getCategoryString(ComparisonCategoryType Kind) {
diff --git a/clang/lib/AST/ComputeDependence.cpp b/clang/lib/AST/ComputeDependence.cpp
index 87334d9..e0cf0de 100644
--- a/clang/lib/AST/ComputeDependence.cpp
+++ b/clang/lib/AST/ComputeDependence.cpp
@@ -500,9 +500,8 @@ ExprDependence clang::computeDependence(OMPIteratorExpr *E) {
ExprDependence clang::computeDependence(DeclRefExpr *E, const ASTContext &Ctx) {
auto Deps = ExprDependence::None;
- if (auto *NNS = E->getQualifier())
- Deps |= toExprDependence(NNS->getDependence() &
- ~NestedNameSpecifierDependence::Dependent);
+ Deps |= toExprDependence(E->getQualifier().getDependence() &
+ ~NestedNameSpecifierDependence::Dependent);
if (auto *FirstArg = E->getTemplateArgs()) {
unsigned NumArgs = E->getNumTemplateArgs();
@@ -673,9 +672,8 @@ ExprDependence clang::computeDependence(MemberExpr *E) {
auto D = E->getBase()->getDependence();
D |= getDependenceInExpr(E->getMemberNameInfo());
- if (auto *NNS = E->getQualifier())
- D |= toExprDependence(NNS->getDependence() &
- ~NestedNameSpecifierDependence::Dependent);
+ D |= toExprDependence(E->getQualifier().getDependence() &
+ ~NestedNameSpecifierDependence::Dependent);
for (const auto &A : E->template_arguments())
D |= toExprDependence(A.getArgument().getDependence());
@@ -783,9 +781,8 @@ ExprDependence clang::computeDependence(CXXPseudoDestructorExpr *E) {
if (auto *ST = E->getScopeTypeInfo())
D |= turnTypeToValueDependence(
toExprDependenceAsWritten(ST->getType()->getDependence()));
- if (auto *Q = E->getQualifier())
- D |= toExprDependence(Q->getDependence() &
- ~NestedNameSpecifierDependence::Dependent);
+ D |= toExprDependence(E->getQualifier().getDependence() &
+ ~NestedNameSpecifierDependence::Dependent);
return D;
}
@@ -801,9 +798,8 @@ clang::computeDependence(OverloadExpr *E, bool KnownDependent,
if (KnownContainsUnexpandedParameterPack)
Deps |= ExprDependence::UnexpandedPack;
Deps |= getDependenceInExpr(E->getNameInfo());
- if (auto *Q = E->getQualifier())
- Deps |= toExprDependence(Q->getDependence() &
- ~NestedNameSpecifierDependence::Dependent);
+ Deps |= toExprDependence(E->getQualifier().getDependence() &
+ ~NestedNameSpecifierDependence::Dependent);
for (auto *D : E->decls()) {
if (D->getDeclContext()->isDependentContext() ||
isa<UnresolvedUsingValueDecl>(D) || isa<TemplateTemplateParmDecl>(D))
@@ -820,8 +816,7 @@ clang::computeDependence(OverloadExpr *E, bool KnownDependent,
ExprDependence clang::computeDependence(DependentScopeDeclRefExpr *E) {
auto D = ExprDependence::TypeValue;
D |= getDependenceInExpr(E->getNameInfo());
- if (auto *Q = E->getQualifier())
- D |= toExprDependence(Q->getDependence());
+ D |= toExprDependence(E->getQualifier().getDependence());
for (const auto &A : E->template_arguments())
D |= toExprDependence(A.getArgument().getDependence());
return D;
@@ -872,8 +867,7 @@ ExprDependence clang::computeDependence(CXXDependentScopeMemberExpr *E) {
auto D = ExprDependence::TypeValueInstantiation;
if (!E->isImplicitAccess())
D |= E->getBase()->getDependence();
- if (auto *Q = E->getQualifier())
- D |= toExprDependence(Q->getDependence());
+ D |= toExprDependence(E->getQualifier().getDependence());
D |= getDependenceInExpr(E->getMemberNameInfo());
for (const auto &A : E->template_arguments())
D |= toExprDependence(A.getArgument().getDependence());
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 5471f31..12fe551 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -1693,9 +1693,9 @@ void NamedDecl::printQualifiedName(raw_ostream &OS,
return;
}
printNestedNameSpecifier(OS, P);
- if (getDeclName())
- OS << *this;
- else {
+ if (getDeclName()) {
+ printName(OS, P);
+ } else {
// Give the printName override a chance to pick a different name before we
// fall back to "(anonymous)".
SmallString<64> NameBuffer;
@@ -1883,18 +1883,13 @@ bool NamedDecl::declarationReplaces(const NamedDecl *OldD,
// Using declarations can be replaced if they import the same name from the
// same context.
- if (const auto *UD = dyn_cast<UsingDecl>(this)) {
- ASTContext &Context = getASTContext();
- return Context.getCanonicalNestedNameSpecifier(UD->getQualifier()) ==
- Context.getCanonicalNestedNameSpecifier(
- cast<UsingDecl>(OldD)->getQualifier());
- }
- if (const auto *UUVD = dyn_cast<UnresolvedUsingValueDecl>(this)) {
- ASTContext &Context = getASTContext();
- return Context.getCanonicalNestedNameSpecifier(UUVD->getQualifier()) ==
- Context.getCanonicalNestedNameSpecifier(
- cast<UnresolvedUsingValueDecl>(OldD)->getQualifier());
- }
+ if (const auto *UD = dyn_cast<UsingDecl>(this))
+ return UD->getQualifier().getCanonical() ==
+
+ cast<UsingDecl>(OldD)->getQualifier().getCanonical();
+ if (const auto *UUVD = dyn_cast<UnresolvedUsingValueDecl>(this))
+ return UUVD->getQualifier().getCanonical() ==
+ cast<UnresolvedUsingValueDecl>(OldD)->getQualifier().getCanonical();
if (isRedeclarable(getKind())) {
if (getCanonicalDecl() != OldD->getCanonicalDecl())
@@ -2864,7 +2859,8 @@ VarDecl::needsDestruction(const ASTContext &Ctx) const {
bool VarDecl::hasFlexibleArrayInit(const ASTContext &Ctx) const {
assert(hasInit() && "Expect initializer to check for flexible array init");
auto *Ty = getType()->getAs<RecordType>();
- if (!Ty || !Ty->getDecl()->hasFlexibleArrayMember())
+ if (!Ty ||
+ !Ty->getOriginalDecl()->getDefinitionOrSelf()->hasFlexibleArrayMember())
return false;
auto *List = dyn_cast<InitListExpr>(getInit()->IgnoreParens());
if (!List)
@@ -2879,7 +2875,10 @@ bool VarDecl::hasFlexibleArrayInit(const ASTContext &Ctx) const {
CharUnits VarDecl::getFlexibleArrayInitChars(const ASTContext &Ctx) const {
assert(hasInit() && "Expect initializer to check for flexible array init");
auto *Ty = getType()->getAs<RecordType>();
- if (!Ty || !Ty->getDecl()->hasFlexibleArrayMember())
+ if (!Ty)
+ return CharUnits::Zero();
+ const RecordDecl *RD = Ty->getOriginalDecl()->getDefinitionOrSelf();
+ if (!Ty || !RD->hasFlexibleArrayMember())
return CharUnits::Zero();
auto *List = dyn_cast<InitListExpr>(getInit()->IgnoreParens());
if (!List || List->getNumInits() == 0)
@@ -2889,7 +2888,7 @@ CharUnits VarDecl::getFlexibleArrayInitChars(const ASTContext &Ctx) const {
if (!InitTy)
return CharUnits::Zero();
CharUnits FlexibleArraySize = Ctx.getTypeSizeInChars(InitTy);
- const ASTRecordLayout &RL = Ctx.getASTRecordLayout(Ty->getDecl());
+ const ASTRecordLayout &RL = Ctx.getASTRecordLayout(RD);
CharUnits FlexibleArrayOffset =
Ctx.toCharUnitsFromBits(RL.getFieldOffset(RL.getFieldCount() - 1));
if (FlexibleArrayOffset + FlexibleArraySize < RL.getSize())
@@ -2991,7 +2990,10 @@ bool ParmVarDecl::isDestroyedInCallee() const {
// FIXME: isParamDestroyedInCallee() should probably imply
// isDestructedType()
const auto *RT = getType()->getAs<RecordType>();
- if (RT && RT->getDecl()->isParamDestroyedInCallee() &&
+ if (RT &&
+ RT->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->isParamDestroyedInCallee() &&
getType().isDestructedType())
return true;
@@ -3502,7 +3504,7 @@ bool FunctionDecl::isUsableAsGlobalAllocationFunctionInConstantEvaluation(
while (const auto *TD = T->getAs<TypedefType>())
T = TD->getDecl()->getUnderlyingType();
const IdentifierInfo *II =
- T->castAs<EnumType>()->getDecl()->getIdentifier();
+ T->castAs<EnumType>()->getOriginalDecl()->getIdentifier();
if (II && II->isStr("__hot_cold_t"))
Consume();
}
@@ -4653,7 +4655,7 @@ bool FieldDecl::isAnonymousStructOrUnion() const {
return false;
if (const auto *Record = getType()->getAs<RecordType>())
- return Record->getDecl()->isAnonymousStructOrUnion();
+ return Record->getOriginalDecl()->isAnonymousStructOrUnion();
return false;
}
@@ -4713,7 +4715,7 @@ bool FieldDecl::isZeroSize(const ASTContext &Ctx) const {
const auto *RT = getType()->getAs<RecordType>();
if (!RT)
return false;
- const RecordDecl *RD = RT->getDecl()->getDefinition();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinition();
if (!RD) {
assert(isInvalidDecl() && "valid field has incomplete type");
return false;
@@ -4836,10 +4838,6 @@ TagDecl *TagDecl::getCanonicalDecl() { return getFirstDecl(); }
void TagDecl::setTypedefNameForAnonDecl(TypedefNameDecl *TDD) {
TypedefNameDeclOrQualifier = TDD;
- if (const Type *T = getTypeForDecl()) {
- (void)T;
- assert(T->isLinkageValid());
- }
assert(isLinkageValid());
}
@@ -4867,25 +4865,16 @@ void TagDecl::completeDefinition() {
}
TagDecl *TagDecl::getDefinition() const {
- if (isCompleteDefinition())
+ if (isCompleteDefinition() || isBeingDefined())
return const_cast<TagDecl *>(this);
- // If it's possible for us to have an out-of-date definition, check now.
- if (mayHaveOutOfDateDef()) {
- if (IdentifierInfo *II = getIdentifier()) {
- if (II->isOutOfDate()) {
- updateOutOfDate(*II);
- }
- }
- }
-
if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(this))
return CXXRD->getDefinition();
- for (auto *R : redecls())
- if (R->isCompleteDefinition())
+ for (TagDecl *R :
+ redecl_range(redecl_iterator(getNextRedeclaration()), redecl_iterator()))
+ if (R->isCompleteDefinition() || R->isBeingDefined())
return R;
-
return nullptr;
}
@@ -4919,7 +4908,7 @@ void TagDecl::printName(raw_ostream &OS, const PrintingPolicy &Policy) const {
// is already printed as part of the type.
PrintingPolicy Copy(Policy);
Copy.SuppressScope = true;
- getASTContext().getTagDeclType(this).print(OS, Copy);
+ QualType(getASTContext().getCanonicalTagType(this)).print(OS, Copy);
return;
}
// Otherwise, do the normal printing.
@@ -4963,19 +4952,13 @@ EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC,
IdentifierInfo *Id,
EnumDecl *PrevDecl, bool IsScoped,
bool IsScopedUsingClassTag, bool IsFixed) {
- auto *Enum = new (C, DC) EnumDecl(C, DC, StartLoc, IdLoc, Id, PrevDecl,
- IsScoped, IsScopedUsingClassTag, IsFixed);
- Enum->setMayHaveOutOfDateDef(C.getLangOpts().Modules);
- C.getTypeDeclType(Enum, PrevDecl);
- return Enum;
+ return new (C, DC) EnumDecl(C, DC, StartLoc, IdLoc, Id, PrevDecl, IsScoped,
+ IsScopedUsingClassTag, IsFixed);
}
EnumDecl *EnumDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
- EnumDecl *Enum =
- new (C, ID) EnumDecl(C, nullptr, SourceLocation(), SourceLocation(),
- nullptr, nullptr, false, false, false);
- Enum->setMayHaveOutOfDateDef(C.getLangOpts().Modules);
- return Enum;
+ return new (C, ID) EnumDecl(C, nullptr, SourceLocation(), SourceLocation(),
+ nullptr, nullptr, false, false, false);
}
SourceRange EnumDecl::getIntegerTypeRange() const {
@@ -5035,7 +5018,7 @@ EnumDecl *EnumDecl::getTemplateInstantiationPattern() const {
EnumDecl *ED = getInstantiatedFromMemberEnum();
while (auto *NewED = ED->getInstantiatedFromMemberEnum())
ED = NewED;
- return getDefinitionOrSelf(ED);
+ return ::getDefinitionOrSelf(ED);
}
}
@@ -5125,21 +5108,15 @@ RecordDecl::RecordDecl(Kind DK, TagKind TK, const ASTContext &C,
RecordDecl *RecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
IdentifierInfo *Id, RecordDecl* PrevDecl) {
- RecordDecl *R = new (C, DC) RecordDecl(Record, TK, C, DC,
- StartLoc, IdLoc, Id, PrevDecl);
- R->setMayHaveOutOfDateDef(C.getLangOpts().Modules);
-
- C.getTypeDeclType(R, PrevDecl);
- return R;
+ return new (C, DC)
+ RecordDecl(Record, TK, C, DC, StartLoc, IdLoc, Id, PrevDecl);
}
RecordDecl *RecordDecl::CreateDeserialized(const ASTContext &C,
GlobalDeclID ID) {
- RecordDecl *R = new (C, ID)
+ return new (C, ID)
RecordDecl(Record, TagTypeKind::Struct, C, nullptr, SourceLocation(),
SourceLocation(), nullptr, nullptr);
- R->setMayHaveOutOfDateDef(C.getLangOpts().Modules);
- return R;
}
bool RecordDecl::isLambda() const {
@@ -5163,7 +5140,7 @@ bool RecordDecl::isOrContainsUnion() const {
if (const RecordDecl *Def = getDefinition()) {
for (const FieldDecl *FD : Def->fields()) {
const RecordType *RT = FD->getType()->getAs<RecordType>();
- if (RT && RT->getDecl()->isOrContainsUnion())
+ if (RT && RT->getOriginalDecl()->isOrContainsUnion())
return true;
}
}
@@ -5295,8 +5272,9 @@ const FieldDecl *RecordDecl::findFirstNamedDataMember() const {
return I;
if (const auto *RT = I->getType()->getAs<RecordType>())
- if (const FieldDecl *NamedDataMember =
- RT->getDecl()->findFirstNamedDataMember())
+ if (const FieldDecl *NamedDataMember = RT->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->findFirstNamedDataMember())
return NamedDataMember;
}
@@ -5658,14 +5636,14 @@ void TypedefNameDecl::anchor() {}
TagDecl *TypedefNameDecl::getAnonDeclWithTypedefName(bool AnyRedecl) const {
if (auto *TT = getTypeSourceInfo()->getType()->getAs<TagType>()) {
- auto *OwningTypedef = TT->getDecl()->getTypedefNameForAnonDecl();
+ auto *OwningTypedef = TT->getOriginalDecl()->getTypedefNameForAnonDecl();
auto *ThisTypedef = this;
if (AnyRedecl && OwningTypedef) {
OwningTypedef = OwningTypedef->getCanonicalDecl();
ThisTypedef = ThisTypedef->getCanonicalDecl();
}
if (OwningTypedef == ThisTypedef)
- return TT->getDecl();
+ return TT->getOriginalDecl()->getDefinitionOrSelf();
}
return nullptr;
@@ -5674,7 +5652,7 @@ TagDecl *TypedefNameDecl::getAnonDeclWithTypedefName(bool AnyRedecl) const {
bool TypedefNameDecl::isTransparentTagSlow() const {
auto determineIsTransparent = [&]() {
if (auto *TT = getUnderlyingType()->getAs<TagType>()) {
- if (auto *TD = TT->getDecl()) {
+ if (auto *TD = TT->getOriginalDecl()) {
if (TD->getName() != getName())
return false;
SourceLocation TTLoc = getLocation();
diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp
index 13c46fd..680a4d7 100644
--- a/clang/lib/AST/DeclBase.cpp
+++ b/clang/lib/AST/DeclBase.cpp
@@ -58,10 +58,6 @@ using namespace clang;
#define ABSTRACT_DECL(DECL)
#include "clang/AST/DeclNodes.inc"
-void Decl::updateOutOfDate(IdentifierInfo &II) const {
- getASTContext().getExternalSource()->updateOutOfDateIdentifier(II);
-}
-
#define DECL(DERIVED, BASE) \
static_assert(alignof(Decl) >= alignof(DERIVED##Decl), \
"Alignment sufficient after objects prepended to " #DERIVED);
@@ -489,8 +485,7 @@ bool Decl::isFlexibleArrayMemberLike(
// Look through typedefs.
if (TypedefTypeLoc TTL = TL.getAsAdjusted<TypedefTypeLoc>()) {
- const TypedefNameDecl *TDL = TTL.getTypedefNameDecl();
- TInfo = TDL->getTypeSourceInfo();
+ TInfo = TTL.getDecl()->getTypeSourceInfo();
continue;
}
@@ -1512,30 +1507,19 @@ DeclContext *DeclContext::getPrimaryContext() {
case Decl::ObjCCategoryImpl:
return this;
- default:
- if (getDeclKind() >= Decl::firstTag && getDeclKind() <= Decl::lastTag) {
- // If this is a tag type that has a definition or is currently
- // being defined, that definition is our primary context.
- auto *Tag = cast<TagDecl>(this);
-
- if (TagDecl *Def = Tag->getDefinition())
- return Def;
-
- if (const auto *TagTy = dyn_cast<TagType>(Tag->getTypeForDecl())) {
- // Note, TagType::getDecl returns the (partial) definition one exists.
- TagDecl *PossiblePartialDef = TagTy->getDecl();
- if (PossiblePartialDef->isBeingDefined())
- return PossiblePartialDef;
- } else {
- assert(isa<InjectedClassNameType>(Tag->getTypeForDecl()));
- }
-
- return Tag;
- }
+ // If this is a tag type that has a definition or is currently
+ // being defined, that definition is our primary context.
+ case Decl::ClassTemplatePartialSpecialization:
+ case Decl::ClassTemplateSpecialization:
+ case Decl::CXXRecord:
+ return cast<CXXRecordDecl>(this)->getDefinitionOrSelf();
+ case Decl::Record:
+ case Decl::Enum:
+ return cast<TagDecl>(this)->getDefinitionOrSelf();
+ default:
assert(getDeclKind() >= Decl::firstFunction &&
- getDeclKind() <= Decl::lastFunction &&
- "Unknown DeclContext kind");
+ getDeclKind() <= Decl::lastFunction && "Unknown DeclContext kind");
return this;
}
}
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 037a28c4..50b1a1d 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -132,16 +132,9 @@ CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, const ASTContext &C,
CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK,
DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id,
- CXXRecordDecl *PrevDecl,
- bool DelayTypeCreation) {
- auto *R = new (C, DC) CXXRecordDecl(CXXRecord, TK, C, DC, StartLoc, IdLoc, Id,
- PrevDecl);
- R->setMayHaveOutOfDateDef(C.getLangOpts().Modules);
-
- // FIXME: DelayTypeCreation seems like such a hack
- if (!DelayTypeCreation)
- C.getTypeDeclType(R, PrevDecl);
- return R;
+ CXXRecordDecl *PrevDecl) {
+ return new (C, DC)
+ CXXRecordDecl(CXXRecord, TK, C, DC, StartLoc, IdLoc, Id, PrevDecl);
}
CXXRecordDecl *
@@ -154,10 +147,7 @@ CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC,
R->setBeingDefined(true);
R->DefinitionData = new (C) struct LambdaDefinitionData(
R, Info, DependencyKind, IsGeneric, CaptureDefault);
- R->setMayHaveOutOfDateDef(false);
R->setImplicit(true);
-
- C.getTypeDeclType(R, /*PrevDecl=*/nullptr);
return R;
}
@@ -166,7 +156,6 @@ CXXRecordDecl *CXXRecordDecl::CreateDeserialized(const ASTContext &C,
auto *R = new (C, ID)
CXXRecordDecl(CXXRecord, TagTypeKind::Struct, C, nullptr,
SourceLocation(), SourceLocation(), nullptr, nullptr);
- R->setMayHaveOutOfDateDef(false);
return R;
}
@@ -178,7 +167,7 @@ static bool hasRepeatedBaseClass(const CXXRecordDecl *StartRD) {
SmallVector<const CXXRecordDecl*, 8> WorkList = {StartRD};
while (!WorkList.empty()) {
const CXXRecordDecl *RD = WorkList.pop_back_val();
- if (RD->getTypeForDecl()->isDependentType())
+ if (RD->isDependentType())
continue;
for (const CXXBaseSpecifier &BaseSpec : RD->bases()) {
if (const CXXRecordDecl *B = BaseSpec.getType()->getAsCXXRecordDecl()) {
@@ -228,7 +217,8 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
if (BaseType->isDependentType())
continue;
auto *BaseClassDecl =
- cast<CXXRecordDecl>(BaseType->castAs<RecordType>()->getDecl());
+ cast<CXXRecordDecl>(BaseType->castAs<RecordType>()->getOriginalDecl())
+ ->getDefinitionOrSelf();
// C++2a [class]p7:
// A standard-layout class is a class that:
@@ -1218,7 +1208,7 @@ void CXXRecordDecl::addedMember(Decl *D) {
bool IsZeroSize = Field->isZeroSize(Context);
if (const auto *RecordTy = T->getAs<RecordType>()) {
- auto *FieldRec = cast<CXXRecordDecl>(RecordTy->getDecl());
+ auto *FieldRec = cast<CXXRecordDecl>(RecordTy->getOriginalDecl());
if (FieldRec->getDefinition()) {
addedClassSubobject(FieldRec);
@@ -1925,7 +1915,8 @@ static void CollectVisibleConversions(
= CXXRecordDecl::MergeAccess(Access, I.getAccessSpecifier());
bool BaseInVirtual = InVirtual || I.isVirtual();
- auto *Base = cast<CXXRecordDecl>(RT->getDecl());
+ auto *Base =
+ cast<CXXRecordDecl>(RT->getOriginalDecl())->getDefinitionOrSelf();
CollectVisibleConversions(Context, Base, BaseInVirtual, BaseAccess,
*HiddenTypes, Output, VOutput, HiddenVBaseCs);
}
@@ -1963,9 +1954,11 @@ static void CollectVisibleConversions(ASTContext &Context,
const auto *RT = I.getType()->getAs<RecordType>();
if (!RT) continue;
- CollectVisibleConversions(Context, cast<CXXRecordDecl>(RT->getDecl()),
- I.isVirtual(), I.getAccessSpecifier(),
- HiddenTypes, Output, VBaseCs, HiddenVBaseCs);
+ CollectVisibleConversions(
+ Context,
+ cast<CXXRecordDecl>(RT->getOriginalDecl())->getDefinitionOrSelf(),
+ I.isVirtual(), I.getAccessSpecifier(), HiddenTypes, Output, VBaseCs,
+ HiddenVBaseCs);
}
// Add any unhidden conversions provided by virtual bases.
@@ -2125,11 +2118,10 @@ const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const {
CXXDestructorDecl *CXXRecordDecl::getDestructor() const {
ASTContext &Context = getASTContext();
- QualType ClassType = Context.getTypeDeclType(this);
+ CanQualType ClassType = Context.getCanonicalTagType(this);
- DeclarationName Name
- = Context.DeclarationNames.getCXXDestructorName(
- Context.getCanonicalType(ClassType));
+ DeclarationName Name =
+ Context.DeclarationNames.getCXXDestructorName(ClassType);
DeclContext::lookup_result R = lookup(Name);
@@ -2159,6 +2151,29 @@ bool CXXRecordDecl::isInjectedClassName() const {
return false;
}
+bool CXXRecordDecl::hasInjectedClassType() const {
+ switch (getDeclKind()) {
+ case Decl::ClassTemplatePartialSpecialization:
+ return true;
+ case Decl::ClassTemplateSpecialization:
+ return false;
+ case Decl::CXXRecord:
+ return getDescribedClassTemplate() != nullptr;
+ default:
+ llvm_unreachable("unexpected decl kind");
+ }
+}
+
+CanQualType CXXRecordDecl::getCanonicalTemplateSpecializationType(
+ const ASTContext &Ctx) const {
+ if (auto *RD = dyn_cast<ClassTemplatePartialSpecializationDecl>(this))
+ return RD->getCanonicalInjectedSpecializationType(Ctx);
+ if (const ClassTemplateDecl *TD = getDescribedClassTemplate();
+ TD && !isa<ClassTemplateSpecializationDecl>(this))
+ return TD->getCanonicalInjectedSpecializationType(Ctx);
+ return CanQualType();
+}
+
static bool isDeclContextInNamespace(const DeclContext *DC) {
while (!DC->isTranslationUnit()) {
if (DC->isNamespace())
@@ -2272,7 +2287,7 @@ void CXXRecordDecl::completeDefinition(CXXFinalOverriderMap *FinalOverriders) {
Context.getDiagnostics().Report(
AT->getLocation(),
diag::warn_cxx20_compat_requires_explicit_init_non_aggregate)
- << AT << FD << Context.getRecordType(this);
+ << AT << FD << Context.getCanonicalTagType(this);
}
}
@@ -2284,7 +2299,7 @@ void CXXRecordDecl::completeDefinition(CXXFinalOverriderMap *FinalOverriders) {
if (const auto *AT = FD->getAttr<ExplicitInitAttr>())
Context.getDiagnostics().Report(AT->getLocation(),
diag::warn_attribute_needs_aggregate)
- << AT << Context.getRecordType(this);
+ << AT << Context.getCanonicalTagType(this);
}
setHasUninitializedExplicitInitFields(false);
}
@@ -2296,8 +2311,8 @@ bool CXXRecordDecl::mayBeAbstract() const {
return false;
for (const auto &B : bases()) {
- const auto *BaseDecl =
- cast<CXXRecordDecl>(B.getType()->castAs<RecordType>()->getDecl());
+ const auto *BaseDecl = cast<CXXRecordDecl>(
+ B.getType()->castAs<RecordType>()->getOriginalDecl());
if (BaseDecl->isAbstract())
return true;
}
@@ -2460,7 +2475,8 @@ CXXMethodDecl::getCorrespondingMethodInClass(const CXXRecordDecl *RD,
const RecordType *RT = I.getType()->getAs<RecordType>();
if (!RT)
continue;
- const auto *Base = cast<CXXRecordDecl>(RT->getDecl());
+ const auto *Base =
+ cast<CXXRecordDecl>(RT->getOriginalDecl())->getDefinitionOrSelf();
if (CXXMethodDecl *D = this->getCorrespondingMethodInClass(Base))
AddFinalOverrider(D);
}
@@ -2712,8 +2728,7 @@ bool CXXMethodDecl::isCopyAssignmentOperator() const {
ParamType = Ref->getPointeeType();
ASTContext &Context = getASTContext();
- QualType ClassType
- = Context.getCanonicalType(Context.getTypeDeclType(getParent()));
+ CanQualType ClassType = Context.getCanonicalTagType(getParent());
return Context.hasSameUnqualifiedType(ClassType, ParamType);
}
@@ -2733,8 +2748,7 @@ bool CXXMethodDecl::isMoveAssignmentOperator() const {
ParamType = ParamType->getPointeeType();
ASTContext &Context = getASTContext();
- QualType ClassType
- = Context.getCanonicalType(Context.getTypeDeclType(getParent()));
+ CanQualType ClassType = Context.getCanonicalTagType(getParent());
return Context.hasSameUnqualifiedType(ClassType, ParamType);
}
@@ -2769,7 +2783,7 @@ CXXMethodDecl::overridden_methods() const {
static QualType getThisObjectType(ASTContext &C, const FunctionProtoType *FPT,
const CXXRecordDecl *Decl) {
- QualType ClassTy = C.getTypeDeclType(Decl);
+ CanQualType ClassTy = C.getCanonicalTagType(Decl);
return C.getQualifiedType(ClassTy, FPT->getMethodQuals());
}
@@ -3027,11 +3041,9 @@ bool CXXConstructorDecl::isCopyOrMoveConstructor(unsigned &TypeQuals) const {
// Is it a reference to our class type?
ASTContext &Context = getASTContext();
- CanQualType PointeeType
- = Context.getCanonicalType(ParamRefType->getPointeeType());
- CanQualType ClassTy
- = Context.getCanonicalType(Context.getTagDeclType(getParent()));
- if (PointeeType.getUnqualifiedType() != ClassTy)
+ QualType PointeeType = ParamRefType->getPointeeType();
+ CanQualType ClassTy = Context.getCanonicalTagType(getParent());
+ if (!Context.hasSameUnqualifiedType(PointeeType, ClassTy))
return false;
// FIXME: other qualifiers?
@@ -3066,15 +3078,11 @@ bool CXXConstructorDecl::isSpecializationCopyingObject() const {
const ParmVarDecl *Param = getParamDecl(0);
ASTContext &Context = getASTContext();
- CanQualType ParamType = Context.getCanonicalType(Param->getType());
+ CanQualType ParamType = Param->getType()->getCanonicalTypeUnqualified();
// Is it the same as our class type?
- CanQualType ClassTy
- = Context.getCanonicalType(Context.getTagDeclType(getParent()));
- if (ParamType.getUnqualifiedType() != ClassTy)
- return false;
-
- return true;
+ CanQualType ClassTy = Context.getCanonicalTagType(getParent());
+ return ParamType == ClassTy;
}
void CXXDestructorDecl::anchor() {}
@@ -3371,7 +3379,7 @@ ConstructorUsingShadowDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
}
CXXRecordDecl *ConstructorUsingShadowDecl::getNominatedBaseClass() const {
- return getIntroducer()->getQualifier()->getAsRecordDecl();
+ return getIntroducer()->getQualifier().getAsRecordDecl();
}
void BaseUsingDecl::anchor() {}
diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp
index f4265dd0..196057f 100644
--- a/clang/lib/AST/DeclPrinter.cpp
+++ b/clang/lib/AST/DeclPrinter.cpp
@@ -202,8 +202,7 @@ void Decl::printGroup(Decl** Begin, unsigned NumDecls,
}
Decl** End = Begin + NumDecls;
- TagDecl* TD = dyn_cast<TagDecl>(*Begin);
- if (TD)
+ if (isa<TagDecl>(*Begin))
++Begin;
PrintingPolicy SubPolicy(Policy);
@@ -211,13 +210,9 @@ void Decl::printGroup(Decl** Begin, unsigned NumDecls,
bool isFirst = true;
for ( ; Begin != End; ++Begin) {
if (isFirst) {
- if(TD)
- SubPolicy.IncludeTagDefinition = true;
- SubPolicy.SuppressSpecifiers = false;
isFirst = false;
} else {
- if (!isFirst) Out << ", ";
- SubPolicy.IncludeTagDefinition = false;
+ Out << ", ";
SubPolicy.SuppressSpecifiers = true;
}
@@ -487,10 +482,12 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
QualType CurDeclType = getDeclType(*D);
if (!Decls.empty() && !CurDeclType.isNull()) {
QualType BaseType = GetBaseType(CurDeclType);
- if (!BaseType.isNull() && isa<ElaboratedType>(BaseType) &&
- cast<ElaboratedType>(BaseType)->getOwnedTagDecl() == Decls[0]) {
- Decls.push_back(*D);
- continue;
+ if (const auto *TT = dyn_cast_or_null<TagType>(BaseType);
+ TT && TT->isTagOwned()) {
+ if (TT->getOriginalDecl() == Decls[0]) {
+ Decls.push_back(*D);
+ continue;
+ }
}
}
@@ -662,16 +659,6 @@ static void printExplicitSpecifier(ExplicitSpecifier ES, llvm::raw_ostream &Out,
Out << Proto;
}
-static void MaybePrintTagKeywordIfSupressingScopes(PrintingPolicy &Policy,
- QualType T,
- llvm::raw_ostream &Out) {
- StringRef prefix = T->isClassType() ? "class "
- : T->isStructureType() ? "struct "
- : T->isUnionType() ? "union "
- : "";
- Out << prefix;
-}
-
void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
if (!D->getDescribedFunctionTemplate() &&
!D->isFunctionTemplateSpecialization()) {
@@ -721,11 +708,8 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
Proto += D->getQualifiedNameAsString();
} else {
llvm::raw_string_ostream OS(Proto);
- if (!Policy.SuppressScope) {
- if (const NestedNameSpecifier *NS = D->getQualifier()) {
- NS->print(OS, Policy);
- }
- }
+ if (!Policy.SuppressScope)
+ D->getQualifier().print(OS, Policy);
D->getNameInfo().printName(OS, Policy);
}
@@ -833,10 +817,6 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
Out << Proto << " -> ";
Proto.clear();
}
- if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
- !Policy.SuppressUnwrittenScope)
- MaybePrintTagKeywordIfSupressingScopes(Policy, AFT->getReturnType(),
- Out);
AFT->getReturnType().print(Out, Policy, Proto);
Proto.clear();
}
@@ -995,10 +975,6 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
}
}
- if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
- !Policy.SuppressUnwrittenScope)
- MaybePrintTagKeywordIfSupressingScopes(Policy, T, Out);
-
printDeclType(T, (isa<ParmVarDecl>(D) && Policy.CleanUglifiedParameters &&
D->getIdentifier())
? D->getIdentifier()->deuglifiedName()
@@ -1028,7 +1004,6 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
}
PrintingPolicy SubPolicy(Policy);
SubPolicy.SuppressSpecifiers = false;
- SubPolicy.IncludeTagDefinition = false;
Init->printPretty(Out, nullptr, SubPolicy, Indentation, "\n", &Context);
if ((D->getInitStyle() == VarDecl::CallInit) && !isa<ParenListExpr>(Init))
Out << ")";
@@ -1086,15 +1061,13 @@ void DeclPrinter::VisitNamespaceDecl(NamespaceDecl *D) {
void DeclPrinter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
Out << "using namespace ";
- if (D->getQualifier())
- D->getQualifier()->print(Out, Policy);
+ D->getQualifier().print(Out, Policy);
Out << *D->getNominatedNamespaceAsWritten();
}
void DeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
Out << "namespace " << *D << " = ";
- if (D->getQualifier())
- D->getQualifier()->print(Out, Policy);
+ D->getQualifier().print(Out, Policy);
Out << *D->getAliasedNamespace();
}
@@ -1115,8 +1088,7 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
Out << ' ';
if (D->getIdentifier()) {
- if (auto *NNS = D->getQualifier())
- NNS->print(Out, Policy);
+ D->getQualifier().print(Out, Policy);
Out << *D;
if (auto *S = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
@@ -1746,7 +1718,7 @@ void DeclPrinter::VisitUsingDecl(UsingDecl *D) {
Out << "using ";
if (D->hasTypename())
Out << "typename ";
- D->getQualifier()->print(Out, Policy);
+ D->getQualifier().print(Out, Policy);
// Use the correct record name when the using declaration is used for
// inheriting constructors.
@@ -1768,14 +1740,14 @@ void DeclPrinter::VisitUsingEnumDecl(UsingEnumDecl *D) {
void
DeclPrinter::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
Out << "using typename ";
- D->getQualifier()->print(Out, Policy);
+ D->getQualifier().print(Out, Policy);
Out << D->getDeclName();
}
void DeclPrinter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
if (!D->isAccessDeclaration())
Out << "using ";
- D->getQualifier()->print(Out, Policy);
+ D->getQualifier().print(Out, Policy);
Out << D->getDeclName();
}
diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp
index bc4a299..8a6fb33 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -632,7 +632,8 @@ ClassTemplateDecl::findPartialSpecialization(QualType T) {
ASTContext &Context = getASTContext();
for (ClassTemplatePartialSpecializationDecl &P :
getPartialSpecializations()) {
- if (Context.hasSameType(P.getInjectedSpecializationType(), T))
+ if (Context.hasSameType(P.getCanonicalInjectedSpecializationType(Context),
+ T))
return P.getMostRecentDecl();
}
@@ -651,28 +652,20 @@ ClassTemplateDecl::findPartialSpecInstantiatedFromMember(
return nullptr;
}
-QualType
-ClassTemplateDecl::getInjectedClassNameSpecialization() {
+CanQualType ClassTemplateDecl::getCanonicalInjectedSpecializationType(
+ const ASTContext &Ctx) const {
Common *CommonPtr = getCommonPtr();
- if (!CommonPtr->InjectedClassNameType.isNull())
- return CommonPtr->InjectedClassNameType;
-
- // C++0x [temp.dep.type]p2:
- // The template argument list of a primary template is a template argument
- // list in which the nth template argument has the value of the nth template
- // parameter of the class template. If the nth template parameter is a
- // template parameter pack (14.5.3), the nth template argument is a pack
- // expansion (14.5.3) whose pattern is the name of the template parameter
- // pack.
- ASTContext &Context = getASTContext();
- TemplateName Name = Context.getQualifiedTemplateName(
- /*NNS=*/nullptr, /*TemplateKeyword=*/false, TemplateName(this));
- auto TemplateArgs = getTemplateParameters()->getInjectedTemplateArgs(Context);
- CommonPtr->InjectedClassNameType =
- Context.getTemplateSpecializationType(Name,
- /*SpecifiedArgs=*/TemplateArgs,
- /*CanonicalArgs=*/{});
- return CommonPtr->InjectedClassNameType;
+
+ if (CommonPtr->CanonInjectedTST.isNull()) {
+ SmallVector<TemplateArgument> CanonicalArgs(
+ getTemplateParameters()->getInjectedTemplateArgs(Ctx));
+ Ctx.canonicalizeTemplateArguments(CanonicalArgs);
+ CommonPtr->CanonInjectedTST =
+ CanQualType::CreateUnsafe(Ctx.getCanonicalTemplateSpecializationType(
+ TemplateName(const_cast<ClassTemplateDecl *>(getCanonicalDecl())),
+ CanonicalArgs));
+ }
+ return CommonPtr->CanonInjectedTST;
}
//===----------------------------------------------------------------------===//
@@ -998,7 +991,6 @@ ClassTemplateSpecializationDecl *ClassTemplateSpecializationDecl::Create(
auto *Result = new (Context, DC) ClassTemplateSpecializationDecl(
Context, ClassTemplateSpecialization, TK, DC, StartLoc, IdLoc,
SpecializedTemplate, Args, StrictPackMatch, PrevDecl);
- Result->setMayHaveOutOfDateDef(false);
// If the template decl is incomplete, copy the external lexical storage from
// the base template. This allows instantiations of incomplete types to
@@ -1008,17 +1000,14 @@ ClassTemplateSpecializationDecl *ClassTemplateSpecializationDecl::Create(
Result->setHasExternalLexicalStorage(
SpecializedTemplate->getTemplatedDecl()->hasExternalLexicalStorage());
- Context.getTypeDeclType(Result, PrevDecl);
return Result;
}
ClassTemplateSpecializationDecl *
ClassTemplateSpecializationDecl::CreateDeserialized(ASTContext &C,
GlobalDeclID ID) {
- auto *Result =
- new (C, ID) ClassTemplateSpecializationDecl(C, ClassTemplateSpecialization);
- Result->setMayHaveOutOfDateDef(false);
- return Result;
+ return new (C, ID)
+ ClassTemplateSpecializationDecl(C, ClassTemplateSpecialization);
}
void ClassTemplateSpecializationDecl::getNameForDiagnostic(
@@ -1180,13 +1169,15 @@ ClassTemplatePartialSpecializationDecl::ClassTemplatePartialSpecializationDecl(
ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, TemplateParameterList *Params,
ClassTemplateDecl *SpecializedTemplate, ArrayRef<TemplateArgument> Args,
+ CanQualType CanonInjectedTST,
ClassTemplatePartialSpecializationDecl *PrevDecl)
: ClassTemplateSpecializationDecl(
Context, ClassTemplatePartialSpecialization, TK, DC, StartLoc, IdLoc,
// Tracking StrictPackMatch for Partial
// Specializations is not needed.
SpecializedTemplate, Args, /*StrictPackMatch=*/false, PrevDecl),
- TemplateParams(Params), InstantiatedFromMember(nullptr, false) {
+ TemplateParams(Params), InstantiatedFromMember(nullptr, false),
+ CanonInjectedTST(CanonInjectedTST) {
if (AdoptTemplateParameterList(Params, this))
setInvalidDecl();
}
@@ -1196,24 +1187,31 @@ ClassTemplatePartialSpecializationDecl::Create(
ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, TemplateParameterList *Params,
ClassTemplateDecl *SpecializedTemplate, ArrayRef<TemplateArgument> Args,
- QualType CanonInjectedType,
+ CanQualType CanonInjectedTST,
ClassTemplatePartialSpecializationDecl *PrevDecl) {
auto *Result = new (Context, DC) ClassTemplatePartialSpecializationDecl(
Context, TK, DC, StartLoc, IdLoc, Params, SpecializedTemplate, Args,
- PrevDecl);
+ CanonInjectedTST, PrevDecl);
Result->setSpecializationKind(TSK_ExplicitSpecialization);
- Result->setMayHaveOutOfDateDef(false);
-
- Context.getInjectedClassNameType(Result, CanonInjectedType);
return Result;
}
ClassTemplatePartialSpecializationDecl *
ClassTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C,
GlobalDeclID ID) {
- auto *Result = new (C, ID) ClassTemplatePartialSpecializationDecl(C);
- Result->setMayHaveOutOfDateDef(false);
- return Result;
+ return new (C, ID) ClassTemplatePartialSpecializationDecl(C);
+}
+
+CanQualType
+ClassTemplatePartialSpecializationDecl::getCanonicalInjectedSpecializationType(
+ const ASTContext &Ctx) const {
+ if (CanonInjectedTST.isNull()) {
+ CanonInjectedTST =
+ CanQualType::CreateUnsafe(Ctx.getCanonicalTemplateSpecializationType(
+ TemplateName(getSpecializedTemplate()->getCanonicalDecl()),
+ getTemplateArgs().asArray()));
+ }
+ return CanonInjectedTST;
}
SourceRange ClassTemplatePartialSpecializationDecl::getSourceRange() const {
diff --git a/clang/lib/AST/DeclarationName.cpp b/clang/lib/AST/DeclarationName.cpp
index ae5fcf6..6c7b995 100644
--- a/clang/lib/AST/DeclarationName.cpp
+++ b/clang/lib/AST/DeclarationName.cpp
@@ -115,12 +115,12 @@ static void printCXXConstructorDestructorName(QualType ClassType,
Policy.adjustForCPlusPlus();
if (const RecordType *ClassRec = ClassType->getAs<RecordType>()) {
- ClassRec->getDecl()->printName(OS, Policy);
+ ClassRec->getOriginalDecl()->printName(OS, Policy);
return;
}
if (Policy.SuppressTemplateArgsInCXXConstructors) {
if (auto *InjTy = ClassType->getAs<InjectedClassNameType>()) {
- InjTy->getDecl()->printName(OS, Policy);
+ InjTy->getOriginalDecl()->printName(OS, Policy);
return;
}
}
@@ -184,7 +184,7 @@ void DeclarationName::print(raw_ostream &OS,
OS << "operator ";
QualType Type = getCXXNameType();
if (const RecordType *Rec = Type->getAs<RecordType>()) {
- OS << *Rec->getDecl();
+ OS << *Rec->getOriginalDecl();
return;
}
// We know we're printing C++ here, ensure we print 'bool' properly.
diff --git a/clang/lib/AST/DynamicRecursiveASTVisitor.cpp b/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
index b478e7a..8821cd3 100644
--- a/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
+++ b/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
@@ -115,8 +115,12 @@ template <bool Const> struct Impl : RecursiveASTVisitor<Impl<Const>> {
bool TraverseAST(ASTContext &AST) { return Visitor.TraverseAST(AST); }
bool TraverseAttr(Attr *At) { return Visitor.TraverseAttr(At); }
bool TraverseDecl(Decl *D) { return Visitor.TraverseDecl(D); }
- bool TraverseType(QualType T) { return Visitor.TraverseType(T); }
- bool TraverseTypeLoc(TypeLoc TL) { return Visitor.TraverseTypeLoc(TL); }
+ bool TraverseType(QualType T, bool TraverseQualifier = true) {
+ return Visitor.TraverseType(T, TraverseQualifier);
+ }
+ bool TraverseTypeLoc(TypeLoc TL, bool TraverseQualifier = true) {
+ return Visitor.TraverseTypeLoc(TL, TraverseQualifier);
+ }
bool TraverseStmt(Stmt *S) { return Visitor.TraverseStmt(S); }
bool TraverseConstructorInitializer(CXXCtorInitializer *Init) {
@@ -172,7 +176,7 @@ template <bool Const> struct Impl : RecursiveASTVisitor<Impl<Const>> {
return Visitor.TraverseLambdaCapture(LE, C, Init);
}
- bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) {
+ bool TraverseNestedNameSpecifier(NestedNameSpecifier NNS) {
return Visitor.TraverseNestedNameSpecifier(NNS);
}
@@ -241,8 +245,8 @@ template <bool Const> struct Impl : RecursiveASTVisitor<Impl<Const>> {
// Types.
#define ABSTRACT_TYPE(CLASS, BASE)
#define TYPE(CLASS, BASE) \
- bool Traverse##CLASS##Type(CLASS##Type *T) { \
- return Visitor.Traverse##CLASS##Type(T); \
+ bool Traverse##CLASS##Type(CLASS##Type *T, bool TraverseQualifier) { \
+ return Visitor.Traverse##CLASS##Type(T, TraverseQualifier); \
}
#include "clang/AST/TypeNodes.inc"
@@ -255,8 +259,8 @@ template <bool Const> struct Impl : RecursiveASTVisitor<Impl<Const>> {
// TypeLocs.
#define ABSTRACT_TYPELOC(CLASS, BASE)
#define TYPELOC(CLASS, BASE) \
- bool Traverse##CLASS##TypeLoc(CLASS##TypeLoc TL) { \
- return Visitor.Traverse##CLASS##TypeLoc(TL); \
+ bool Traverse##CLASS##TypeLoc(CLASS##TypeLoc TL, bool TraverseQualifier) { \
+ return Visitor.Traverse##CLASS##TypeLoc(TL, TraverseQualifier); \
}
#include "clang/AST/TypeLocNodes.def"
@@ -297,7 +301,6 @@ FORWARD_TO_BASE(TraverseAttr, Attr, *)
FORWARD_TO_BASE(TraverseConstructorInitializer, CXXCtorInitializer, *)
FORWARD_TO_BASE(TraverseDecl, Decl, *)
FORWARD_TO_BASE(TraverseStmt, Stmt, *)
-FORWARD_TO_BASE(TraverseNestedNameSpecifier, NestedNameSpecifier, *)
FORWARD_TO_BASE(TraverseTemplateInstantiations, ClassTemplateDecl, *)
FORWARD_TO_BASE(TraverseTemplateInstantiations, VarTemplateDecl, *)
FORWARD_TO_BASE(TraverseTemplateInstantiations, FunctionTemplateDecl, *)
@@ -314,8 +317,22 @@ FORWARD_TO_BASE_EXACT(TraverseTemplateArgument, const TemplateArgument &)
FORWARD_TO_BASE_EXACT(TraverseTemplateArguments, ArrayRef<TemplateArgument>)
FORWARD_TO_BASE_EXACT(TraverseTemplateArgumentLoc, const TemplateArgumentLoc &)
FORWARD_TO_BASE_EXACT(TraverseTemplateName, TemplateName)
-FORWARD_TO_BASE_EXACT(TraverseType, QualType)
-FORWARD_TO_BASE_EXACT(TraverseTypeLoc, TypeLoc)
+FORWARD_TO_BASE_EXACT(TraverseNestedNameSpecifier, NestedNameSpecifier)
+
+template <bool Const>
+bool DynamicRecursiveASTVisitorBase<Const>::TraverseType(
+ QualType T, bool TraverseQualifier) {
+ return Impl<Const>(*this).RecursiveASTVisitor<Impl<Const>>::TraverseType(
+ T, TraverseQualifier);
+}
+
+template <bool Const>
+bool DynamicRecursiveASTVisitorBase<Const>::TraverseTypeLoc(
+ TypeLoc TL, bool TraverseQualifier) {
+ return Impl<Const>(*this).RecursiveASTVisitor<Impl<Const>>::TraverseTypeLoc(
+ TL, TraverseQualifier);
+}
+
FORWARD_TO_BASE_EXACT(TraverseTypeConstraint, const TypeConstraint *)
FORWARD_TO_BASE_EXACT(TraverseObjCProtocolLoc, ObjCProtocolLoc)
FORWARD_TO_BASE_EXACT(TraverseNestedNameSpecifierLoc, NestedNameSpecifierLoc)
@@ -354,13 +371,25 @@ bool DynamicRecursiveASTVisitorBase<Const>::dataTraverseNode(
// Declare Traverse*() and friends for all concrete Type classes.
#define ABSTRACT_TYPE(CLASS, BASE)
#define TYPE(CLASS, BASE) \
- FORWARD_TO_BASE(Traverse##CLASS##Type, CLASS##Type, *) \
+ template <bool Const> \
+ bool DynamicRecursiveASTVisitorBase<Const>::Traverse##CLASS##Type( \
+ MaybeConst<CLASS##Type> *T, bool TraverseQualifier) { \
+ return Impl<Const>(*this) \
+ .RecursiveASTVisitor<Impl<Const>>::Traverse##CLASS##Type( \
+ const_cast<CLASS##Type *>(T), TraverseQualifier); \
+ } \
FORWARD_TO_BASE(WalkUpFrom##CLASS##Type, CLASS##Type, *)
#include "clang/AST/TypeNodes.inc"
#define ABSTRACT_TYPELOC(CLASS, BASE)
#define TYPELOC(CLASS, BASE) \
- FORWARD_TO_BASE_EXACT(Traverse##CLASS##TypeLoc, CLASS##TypeLoc)
+ template <bool Const> \
+ bool DynamicRecursiveASTVisitorBase<Const>::Traverse##CLASS##TypeLoc( \
+ CLASS##TypeLoc TL, bool TraverseQualifier) { \
+ return Impl<Const>(*this) \
+ .RecursiveASTVisitor<Impl<Const>>::Traverse##CLASS##TypeLoc( \
+ TL, TraverseQualifier); \
+ }
#include "clang/AST/TypeLocNodes.def"
#define TYPELOC(CLASS, BASE) \
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index cd9672d..7cac655 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -75,8 +75,7 @@ const CXXRecordDecl *Expr::getBestDynamicClassType() const {
return nullptr;
const RecordType *Ty = DerivedType->castAs<RecordType>();
- Decl *D = Ty->getDecl();
- return cast<CXXRecordDecl>(D);
+ return cast<CXXRecordDecl>(Ty->getOriginalDecl())->getDefinitionOrSelf();
}
const Expr *Expr::skipRValueSubobjectAdjustments(
@@ -92,7 +91,9 @@ const Expr *Expr::skipRValueSubobjectAdjustments(
E->getType()->isRecordType()) {
E = CE->getSubExpr();
const auto *Derived =
- cast<CXXRecordDecl>(E->getType()->castAs<RecordType>()->getDecl());
+ cast<CXXRecordDecl>(
+ E->getType()->castAs<RecordType>()->getOriginalDecl())
+ ->getDefinitionOrSelf();
Adjustments.push_back(SubobjectAdjustment(CE, Derived));
continue;
}
@@ -268,7 +269,7 @@ QualType Expr::getEnumCoercedType(const ASTContext &Ctx) const {
if (const auto *ECD = getEnumConstantDecl()) {
const auto *ED = cast<EnumDecl>(ECD->getDeclContext());
if (ED->isCompleteDefinition())
- return Ctx.getTypeDeclType(ED);
+ return Ctx.getCanonicalTagType(ED);
}
return getType();
}
@@ -2031,7 +2032,8 @@ CXXBaseSpecifier **CastExpr::path_buffer() {
const FieldDecl *CastExpr::getTargetFieldForToUnionCast(QualType unionType,
QualType opType) {
- auto RD = unionType->castAs<RecordType>()->getDecl();
+ auto RD =
+ unionType->castAs<RecordType>()->getOriginalDecl()->getDefinitionOrSelf();
return getTargetFieldForToUnionCast(RD, opType);
}
@@ -3221,7 +3223,7 @@ static const Expr *skipTemporaryBindingsNoOpCastsAndParens(const Expr *E) {
/// isTemporaryObject - Determines if this expression produces a
/// temporary of the given class type.
bool Expr::isTemporaryObject(ASTContext &C, const CXXRecordDecl *TempTy) const {
- if (!C.hasSameUnqualifiedType(getType(), C.getTypeDeclType(TempTy)))
+ if (!C.hasSameUnqualifiedType(getType(), C.getCanonicalTagType(TempTy)))
return false;
const Expr *E = skipTemporaryBindingsNoOpCastsAndParens(this);
@@ -3407,7 +3409,10 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef,
if (ILE->getType()->isRecordType()) {
unsigned ElementNo = 0;
- RecordDecl *RD = ILE->getType()->castAs<RecordType>()->getDecl();
+ RecordDecl *RD = ILE->getType()
+ ->castAs<RecordType>()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf();
// In C++17, bases were added to the list of members used by aggregate
// initialization.
@@ -4050,8 +4055,10 @@ Expr::isNullPointerConstant(ASTContext &Ctx,
return NPCK_CXX11_nullptr;
if (const RecordType *UT = getType()->getAsUnionType())
- if (!Ctx.getLangOpts().CPlusPlus11 &&
- UT && UT->getDecl()->hasAttr<TransparentUnionAttr>())
+ if (!Ctx.getLangOpts().CPlusPlus11 && UT &&
+ UT->getOriginalDecl()
+ ->getMostRecentDecl()
+ ->hasAttr<TransparentUnionAttr>())
if (const CompoundLiteralExpr *CLE = dyn_cast<CompoundLiteralExpr>(this)){
const Expr *InitExpr = CLE->getInitializer();
if (const InitListExpr *ILE = dyn_cast<InitListExpr>(InitExpr))
diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp
index a099e97..97ae4a0 100644
--- a/clang/lib/AST/ExprCXX.cpp
+++ b/clang/lib/AST/ExprCXX.cpp
@@ -1319,7 +1319,7 @@ LambdaExpr *LambdaExpr::Create(const ASTContext &Context, CXXRecordDecl *Class,
bool ContainsUnexpandedParameterPack) {
// Determine the type of the expression (i.e., the type of the
// function object we're creating).
- QualType T = Context.getTypeDeclType(Class);
+ CanQualType T = Context.getCanonicalTagType(Class);
unsigned Size = totalSizeToAlloc<Stmt *>(CaptureInits.size() + 1);
void *Mem = Context.Allocate(Size);
@@ -1687,10 +1687,9 @@ CXXRecordDecl *UnresolvedMemberExpr::getNamingClass() {
// It can't be dependent: after all, we were actually able to do the
// lookup.
CXXRecordDecl *Record = nullptr;
- auto *NNS = getQualifier();
- if (NNS && NNS->getKind() != NestedNameSpecifier::Super) {
- const Type *T = getQualifier()->getAsType();
- assert(T && "qualifier in member expression does not name type");
+ if (NestedNameSpecifier Qualifier = getQualifier();
+ Qualifier.getKind() == NestedNameSpecifier::Kind::Type) {
+ const Type *T = getQualifier().getAsType();
Record = T->getAsCXXRecordDecl();
assert(Record && "qualifier in member expression does not name record");
}
diff --git a/clang/lib/AST/ExprConcepts.cpp b/clang/lib/AST/ExprConcepts.cpp
index ac0e566..36f910d 100644
--- a/clang/lib/AST/ExprConcepts.cpp
+++ b/clang/lib/AST/ExprConcepts.cpp
@@ -41,10 +41,10 @@ ConceptSpecializationExpr::ConceptSpecializationExpr(
assert(!Loc->getNestedNameSpecifierLoc() ||
(!Loc->getNestedNameSpecifierLoc()
.getNestedNameSpecifier()
- ->isInstantiationDependent() &&
+ .isInstantiationDependent() &&
!Loc->getNestedNameSpecifierLoc()
.getNestedNameSpecifier()
- ->containsUnexpandedParameterPack()));
+ .containsUnexpandedParameterPack()));
assert((!isValueDependent() || isInstantiationDependent()) &&
"should not be value-dependent");
}
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 34af9cc..5cf2b9a 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -401,7 +401,7 @@ namespace {
assert(!Invalid && "invalid designator has no subobject type");
return MostDerivedPathLength == Entries.size()
? MostDerivedType
- : Ctx.getRecordType(getAsBaseClass(Entries.back()));
+ : Ctx.getCanonicalTagType(getAsBaseClass(Entries.back()));
}
/// Update this designator to refer to the first element within this array.
@@ -2623,7 +2623,8 @@ static bool CheckEvaluationResult(CheckEvaluationResultKind CERK,
Value.getUnionValue(), Kind, Value.getUnionField(), CheckedTemps);
}
if (Value.isStruct()) {
- RecordDecl *RD = Type->castAs<RecordType>()->getDecl();
+ RecordDecl *RD =
+ Type->castAs<RecordType>()->getOriginalDecl()->getDefinitionOrSelf();
if (const CXXRecordDecl *CD = dyn_cast<CXXRecordDecl>(RD)) {
unsigned BaseIndex = 0;
for (const CXXBaseSpecifier &BS : CD->bases()) {
@@ -4109,7 +4110,7 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj,
}
// Next subobject is a class, struct or union field.
- RecordDecl *RD = ObjType->castAs<RecordType>()->getDecl();
+ RecordDecl *RD = ObjType->castAs<RecordType>()->getOriginalDecl();
if (RD->isUnion()) {
const FieldDecl *UnionField = O->getUnionField();
if (!UnionField ||
@@ -4144,7 +4145,7 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj,
const CXXRecordDecl *Base = getAsBaseClass(Sub.Entries[I]);
O = &O->getStructBase(getBaseIndex(Derived, Base));
- ObjType = getSubobjectType(ObjType, Info.Ctx.getRecordType(Base));
+ ObjType = getSubobjectType(ObjType, Info.Ctx.getCanonicalTagType(Base));
}
}
}
@@ -6363,7 +6364,7 @@ static bool HandleDynamicCast(EvalInfo &Info, const ExplicitCastExpr *E,
const CXXRecordDecl *C = E->getTypeAsWritten()->getPointeeCXXRecordDecl();
assert(C && "dynamic_cast target is not void pointer nor class");
- CanQualType CQT = Info.Ctx.getCanonicalType(Info.Ctx.getRecordType(C));
+ CanQualType CQT = Info.Ctx.getCanonicalTagType(C);
auto RuntimeCheckFailed = [&] (CXXBasePaths *Paths) {
// C++ [expr.dynamic.cast]p9:
@@ -6389,7 +6390,7 @@ static bool HandleDynamicCast(EvalInfo &Info, const ExplicitCastExpr *E,
}
Info.FFDiag(E, diag::note_constexpr_dynamic_cast_to_reference_failed)
<< DiagKind << Ptr.Designator.getType(Info.Ctx)
- << Info.Ctx.getRecordType(DynType->Type)
+ << Info.Ctx.getCanonicalTagType(DynType->Type)
<< E->getType().getUnqualifiedType();
return false;
};
@@ -6886,8 +6887,8 @@ static bool HandleConstructorCall(const Expr *E, const LValue &This,
// FIXME: This immediately starts the lifetime of all members of
// an anonymous struct. It would be preferable to strictly start
// member lifetime in initialization order.
- Success &=
- handleDefaultInitValue(Info.Ctx.getRecordType(CD), *Value);
+ Success &= handleDefaultInitValue(Info.Ctx.getCanonicalTagType(CD),
+ *Value);
}
// Store Subobject as its parent before updating it for the last element
// in the chain.
@@ -7794,7 +7795,8 @@ class BufferToAPValueConverter {
}
std::optional<APValue> visit(const EnumType *Ty, CharUnits Offset) {
- QualType RepresentationType = Ty->getDecl()->getIntegerType();
+ QualType RepresentationType =
+ Ty->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
assert(!RepresentationType.isNull() &&
"enum forward decl should be caught by Sema");
const auto *AsBuiltin =
@@ -8528,7 +8530,7 @@ public:
if (auto *DD = dyn_cast<CXXDestructorDecl>(FD)) {
assert(This && "no 'this' pointer for destructor call");
return HandleDestruction(Info, E, *This,
- Info.Ctx.getRecordType(DD->getParent())) &&
+ Info.Ctx.getCanonicalTagType(DD->getParent())) &&
CallScope.destroy();
}
@@ -8589,8 +8591,10 @@ public:
const FieldDecl *FD = dyn_cast<FieldDecl>(E->getMemberDecl());
if (!FD) return Error(E);
assert(!FD->getType()->isReferenceType() && "prvalue reference?");
- assert(BaseTy->castAs<RecordType>()->getDecl()->getCanonicalDecl() ==
- FD->getParent()->getCanonicalDecl() && "record / field mismatch");
+ assert(
+ BaseTy->castAs<RecordType>()->getOriginalDecl()->getCanonicalDecl() ==
+ FD->getParent()->getCanonicalDecl() &&
+ "record / field mismatch");
// Note: there is no lvalue base here. But this case should only ever
// happen in C or in C++98, where we cannot be evaluating a constexpr
@@ -8817,8 +8821,10 @@ public:
const ValueDecl *MD = E->getMemberDecl();
if (const FieldDecl *FD = dyn_cast<FieldDecl>(E->getMemberDecl())) {
- assert(BaseTy->castAs<RecordType>()->getDecl()->getCanonicalDecl() ==
- FD->getParent()->getCanonicalDecl() && "record / field mismatch");
+ assert(
+ BaseTy->castAs<RecordType>()->getOriginalDecl()->getCanonicalDecl() ==
+ FD->getParent()->getCanonicalDecl() &&
+ "record / field mismatch");
(void)BaseTy;
if (!HandleLValueMember(this->Info, E, Result, FD))
return false;
@@ -9257,8 +9263,8 @@ bool LValueExprEvaluator::VisitCXXTypeidExpr(const CXXTypeidExpr *E) {
if (!DynType)
return false;
- TypeInfo =
- TypeInfoLValue(Info.Ctx.getRecordType(DynType->Type).getTypePtr());
+ TypeInfo = TypeInfoLValue(
+ Info.Ctx.getCanonicalTagType(DynType->Type).getTypePtr());
}
return Success(APValue::LValueBase::getTypeInfo(TypeInfo, E->getType()));
@@ -9860,11 +9866,15 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr *E) {
if (Value.isInt()) {
unsigned Size = Info.Ctx.getTypeSize(E->getType());
uint64_t N = Value.getInt().extOrTrunc(Size).getZExtValue();
- Result.Base = (Expr*)nullptr;
- Result.InvalidBase = false;
- Result.Offset = CharUnits::fromQuantity(N);
- Result.Designator.setInvalid();
- Result.IsNullPtr = false;
+ if (N == Info.Ctx.getTargetNullPointerValue(E->getType())) {
+ Result.setNull(Info.Ctx, E->getType());
+ } else {
+ Result.Base = (Expr *)nullptr;
+ Result.InvalidBase = false;
+ Result.Offset = CharUnits::fromQuantity(N);
+ Result.Designator.setInvalid();
+ Result.IsNullPtr = false;
+ }
return true;
} else {
// In rare instances, the value isn't an lvalue.
@@ -10814,7 +10824,8 @@ static bool HandleClassZeroInitialization(EvalInfo &Info, const Expr *E,
}
bool RecordExprEvaluator::ZeroInitialization(const Expr *E, QualType T) {
- const RecordDecl *RD = T->castAs<RecordType>()->getDecl();
+ const RecordDecl *RD =
+ T->castAs<RecordType>()->getOriginalDecl()->getDefinitionOrSelf();
if (RD->isInvalidDecl()) return false;
if (RD->isUnion()) {
// C++11 [dcl.init]p5: If T is a (possibly cv-qualified) union type, the
@@ -10883,8 +10894,10 @@ bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
bool RecordExprEvaluator::VisitCXXParenListOrInitListExpr(
const Expr *ExprToVisit, ArrayRef<Expr *> Args) {
- const RecordDecl *RD =
- ExprToVisit->getType()->castAs<RecordType>()->getDecl();
+ const RecordDecl *RD = ExprToVisit->getType()
+ ->castAs<RecordType>()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf();
if (RD->isInvalidDecl()) return false;
const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(RD);
auto *CXXRD = dyn_cast<CXXRecordDecl>(RD);
@@ -11112,7 +11125,10 @@ bool RecordExprEvaluator::VisitCXXStdInitializerListExpr(
Result = APValue(APValue::UninitStruct(), 0, 2);
Array.moveInto(Result.getStructField(0));
- RecordDecl *Record = E->getType()->castAs<RecordType>()->getDecl();
+ RecordDecl *Record = E->getType()
+ ->castAs<RecordType>()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf();
RecordDecl::field_iterator Field = Record->field_begin();
assert(Field != Record->field_end() &&
Info.Ctx.hasSameType(Field->getType()->getPointeeType(),
@@ -11624,7 +11640,13 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
return Success(APValue(ResultElements.data(), ResultElements.size()), E);
}
case Builtin::BI__builtin_elementwise_add_sat:
- case Builtin::BI__builtin_elementwise_sub_sat: {
+ case Builtin::BI__builtin_elementwise_sub_sat:
+ case clang::X86::BI__builtin_ia32_pmulhuw128:
+ case clang::X86::BI__builtin_ia32_pmulhuw256:
+ case clang::X86::BI__builtin_ia32_pmulhuw512:
+ case clang::X86::BI__builtin_ia32_pmulhw128:
+ case clang::X86::BI__builtin_ia32_pmulhw256:
+ case clang::X86::BI__builtin_ia32_pmulhw512: {
APValue SourceLHS, SourceRHS;
if (!EvaluateAsRValue(Info, E->getArg(0), SourceLHS) ||
!EvaluateAsRValue(Info, E->getArg(1), SourceRHS))
@@ -11649,6 +11671,18 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
APSInt(LHS.isSigned() ? LHS.ssub_sat(RHS) : LHS.usub_sat(RHS),
DestEltTy->isUnsignedIntegerOrEnumerationType())));
break;
+ case clang::X86::BI__builtin_ia32_pmulhuw128:
+ case clang::X86::BI__builtin_ia32_pmulhuw256:
+ case clang::X86::BI__builtin_ia32_pmulhuw512:
+ ResultElements.push_back(APValue(APSInt(llvm::APIntOps::mulhu(LHS, RHS),
+ /*isUnsigned=*/true)));
+ break;
+ case clang::X86::BI__builtin_ia32_pmulhw128:
+ case clang::X86::BI__builtin_ia32_pmulhw256:
+ case clang::X86::BI__builtin_ia32_pmulhw512:
+ ResultElements.push_back(APValue(APSInt(llvm::APIntOps::mulhs(LHS, RHS),
+ /*isUnsigned=*/false)));
+ break;
}
}
@@ -12885,7 +12919,10 @@ static bool convertUnsignedAPIntToCharUnits(const llvm::APInt &Int,
static void addFlexibleArrayMemberInitSize(EvalInfo &Info, const QualType &T,
const LValue &LV, CharUnits &Size) {
if (!T.isNull() && T->isStructureType() &&
- T->getAsStructureType()->getDecl()->hasFlexibleArrayMember())
+ T->getAsStructureType()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->hasFlexibleArrayMember())
if (const auto *V = LV.getLValueBase().dyn_cast<const ValueDecl *>())
if (const auto *VD = dyn_cast<VarDecl>(V))
if (VD->hasInit())
@@ -15132,7 +15169,7 @@ bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *OOE) {
const RecordType *RT = CurrentType->getAs<RecordType>();
if (!RT)
return Error(OOE);
- RecordDecl *RD = RT->getDecl();
+ RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
if (RD->isInvalidDecl()) return false;
const ASTRecordLayout &RL = Info.Ctx.getASTRecordLayout(RD);
unsigned i = MemberDecl->getFieldIndex();
@@ -15154,7 +15191,7 @@ bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *OOE) {
const RecordType *RT = CurrentType->getAs<RecordType>();
if (!RT)
return Error(OOE);
- RecordDecl *RD = RT->getDecl();
+ RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
if (RD->isInvalidDecl()) return false;
const ASTRecordLayout &RL = Info.Ctx.getASTRecordLayout(RD);
@@ -15165,7 +15202,8 @@ bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *OOE) {
return Error(OOE);
// Add the offset to the base.
- Result += RL.getBaseClassOffset(cast<CXXRecordDecl>(BaseRT->getDecl()));
+ Result += RL.getBaseClassOffset(cast<CXXRecordDecl>(
+ BaseRT->getOriginalDecl()->getDefinitionOrSelf()));
break;
}
}
@@ -15344,7 +15382,7 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) {
if (Info.Ctx.getLangOpts().CPlusPlus && DestType->isEnumeralType()) {
const EnumType *ET = dyn_cast<EnumType>(DestType.getCanonicalType());
- const EnumDecl *ED = ET->getDecl();
+ const EnumDecl *ED = ET->getOriginalDecl()->getDefinitionOrSelf();
// Check that the value is within the range of the enumeration values.
//
// This corressponds to [expr.static.cast]p10 which says:
@@ -18006,7 +18044,8 @@ bool Expr::isPotentialConstantExpr(const FunctionDecl *FD,
// Fabricate an arbitrary expression on the stack and pretend that it
// is a temporary being used as the 'this' pointer.
LValue This;
- ImplicitValueInitExpr VIE(RD ? Info.Ctx.getRecordType(RD) : Info.Ctx.IntTy);
+ ImplicitValueInitExpr VIE(RD ? Info.Ctx.getCanonicalTagType(RD)
+ : Info.Ctx.IntTy);
This.set({&VIE, Info.CurrentCall->Index});
ArrayRef<const Expr*> Args;
diff --git a/clang/lib/AST/FormatString.cpp b/clang/lib/AST/FormatString.cpp
index 112b756d..502a3e6 100644
--- a/clang/lib/AST/FormatString.cpp
+++ b/clang/lib/AST/FormatString.cpp
@@ -417,10 +417,11 @@ ArgType::matchesType(ASTContext &C, QualType argTy) const {
// If the enum is incomplete we know nothing about the underlying type.
// Assume that it's 'int'. Do not use the underlying type for a scoped
// enumeration.
- if (!ETy->getDecl()->isComplete())
+ const EnumDecl *ED = ETy->getOriginalDecl()->getDefinitionOrSelf();
+ if (!ED->isComplete())
return NoMatch;
if (ETy->isUnscopedEnumerationType())
- argTy = ETy->getDecl()->getIntegerType();
+ argTy = ED->getIntegerType();
}
if (const auto *BT = argTy->getAs<BuiltinType>()) {
@@ -466,10 +467,11 @@ ArgType::matchesType(ASTContext &C, QualType argTy) const {
// If the enum is incomplete we know nothing about the underlying type.
// Assume that it's 'int'. Do not use the underlying type for a scoped
// enumeration as that needs an exact match.
- if (!ETy->getDecl()->isComplete())
+ const EnumDecl *ED = ETy->getOriginalDecl()->getDefinitionOrSelf();
+ if (!ED->isComplete())
argTy = C.IntTy;
else if (ETy->isUnscopedEnumerationType())
- argTy = ETy->getDecl()->getIntegerType();
+ argTy = ED->getIntegerType();
}
if (argTy->isSaturatedFixedPointType())
diff --git a/clang/lib/AST/InheritViz.cpp b/clang/lib/AST/InheritViz.cpp
index 1dafed8..c03492c 100644
--- a/clang/lib/AST/InheritViz.cpp
+++ b/clang/lib/AST/InheritViz.cpp
@@ -89,8 +89,8 @@ void InheritanceHierarchyWriter::WriteNode(QualType Type, bool FromVirtual) {
Out << " \"];\n";
// Display the base classes.
- const auto *Decl =
- static_cast<const CXXRecordDecl *>(Type->castAs<RecordType>()->getDecl());
+ const auto *Decl = static_cast<const CXXRecordDecl *>(
+ Type->castAs<RecordType>()->getOriginalDecl());
for (const auto &Base : Decl->bases()) {
QualType CanonBaseType = Context.getCanonicalType(Base.getType());
@@ -133,7 +133,7 @@ InheritanceHierarchyWriter::WriteNodeReference(QualType Type,
/// viewInheritance - Display the inheritance hierarchy of this C++
/// class using GraphViz.
void CXXRecordDecl::viewInheritance(ASTContext& Context) const {
- QualType Self = Context.getTypeDeclType(this);
+ QualType Self = Context.getCanonicalTagType(this);
int FD;
SmallString<128> Filename;
diff --git a/clang/lib/AST/ItaniumCXXABI.cpp b/clang/lib/AST/ItaniumCXXABI.cpp
index 6ceedd6..43a8bcd 100644
--- a/clang/lib/AST/ItaniumCXXABI.cpp
+++ b/clang/lib/AST/ItaniumCXXABI.cpp
@@ -42,10 +42,10 @@ namespace {
///
/// Returns the name of anonymous union VarDecl or nullptr if it is not found.
static const IdentifierInfo *findAnonymousUnionVarDeclName(const VarDecl& VD) {
- const RecordType *RT = VD.getType()->getAs<RecordType>();
- assert(RT && "type of VarDecl is expected to be RecordType.");
- assert(RT->getDecl()->isUnion() && "RecordType is expected to be a union.");
- if (const FieldDecl *FD = RT->getDecl()->findFirstNamedDataMember()) {
+ const auto *RT = VD.getType()->castAs<RecordType>();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
+ assert(RD->isUnion() && "RecordType is expected to be a union.");
+ if (const FieldDecl *FD = RD->findFirstNamedDataMember()) {
return FD->getIdentifier();
}
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 5233648..a7380a1 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -463,9 +463,7 @@ public:
void mangleVendorType(StringRef Name);
private:
-
bool mangleSubstitution(const NamedDecl *ND);
- bool mangleSubstitution(NestedNameSpecifier *NNS);
bool mangleSubstitution(QualType T);
bool mangleSubstitution(TemplateName Template);
bool mangleSubstitution(uintptr_t Ptr);
@@ -479,21 +477,15 @@ private:
addSubstitution(reinterpret_cast<uintptr_t>(ND));
}
- void addSubstitution(NestedNameSpecifier *NNS) {
- NNS = Context.getASTContext().getCanonicalNestedNameSpecifier(NNS);
-
- addSubstitution(reinterpret_cast<uintptr_t>(NNS));
- }
void addSubstitution(QualType T);
void addSubstitution(TemplateName Template);
void addSubstitution(uintptr_t Ptr);
// Destructive copy substitutions from other mangler.
void extendSubstitutions(CXXNameMangler* Other);
- void mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
+ void mangleUnresolvedPrefix(NestedNameSpecifier Qualifier,
bool recursive = false);
- void mangleUnresolvedName(NestedNameSpecifier *qualifier,
- DeclarationName name,
+ void mangleUnresolvedName(NestedNameSpecifier Qualifier, DeclarationName name,
const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs,
unsigned KnownArity = UnknownArity);
@@ -542,7 +534,7 @@ private:
void mangleNestedNameWithClosurePrefix(GlobalDecl GD,
const NamedDecl *PrefixND,
const AbiTagList *AdditionalAbiTags);
- void manglePrefix(NestedNameSpecifier *qualifier);
+ void manglePrefix(NestedNameSpecifier Qualifier);
void manglePrefix(const DeclContext *DC, bool NoFunction=false);
void manglePrefix(QualType type);
void mangleTemplatePrefix(GlobalDecl GD, bool NoFunction=false);
@@ -588,12 +580,10 @@ private:
void mangleMemberExprBase(const Expr *base, bool isArrow);
void mangleMemberExpr(const Expr *base, bool isArrow,
- NestedNameSpecifier *qualifier,
- NamedDecl *firstQualifierLookup,
- DeclarationName name,
+ NestedNameSpecifier Qualifier,
+ NamedDecl *firstQualifierLookup, DeclarationName name,
const TemplateArgumentLoc *TemplateArgs,
- unsigned NumTemplateArgs,
- unsigned knownArity);
+ unsigned NumTemplateArgs, unsigned knownArity);
void mangleCastExpression(const Expr *E, StringRef CastEncoding);
void mangleInitListElements(const InitListExpr *InitList);
void mangleRequirement(SourceLocation RequiresExprLoc,
@@ -1334,6 +1324,21 @@ void CXXNameMangler::manglePrefix(QualType type) {
mangleTemplateArgs(Template, DTST->template_arguments());
addSubstitution(QualType(DTST, 0));
}
+ } else if (const auto *DNT = type->getAs<DependentNameType>()) {
+ // Clang 14 and before did not consider this substitutable.
+ bool Clang14Compat = isCompatibleWith(LangOptions::ClangABI::Ver14);
+ if (!Clang14Compat && mangleSubstitution(QualType(DNT, 0)))
+ return;
+
+ // Member expressions can have these without prefixes, but that
+ // should end up in mangleUnresolvedPrefix instead.
+ assert(DNT->getQualifier());
+ manglePrefix(DNT->getQualifier());
+
+ mangleSourceName(DNT->getIdentifier());
+
+ if (!Clang14Compat)
+ addSubstitution(QualType(DNT, 0));
} else {
// We use the QualType mangle type variant here because it handles
// substitutions.
@@ -1345,7 +1350,7 @@ void CXXNameMangler::manglePrefix(QualType type) {
///
/// \param recursive - true if this is being called recursively,
/// i.e. if there is more prefix "to the right".
-void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
+void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier Qualifier,
bool recursive) {
// x, ::x
@@ -1362,8 +1367,11 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
// <unresolved-name> ::= [gs] sr <unresolved-qualifier-level>+ E
// <base-unresolved-name>
- switch (qualifier->getKind()) {
- case NestedNameSpecifier::Global:
+ switch (Qualifier.getKind()) {
+ case NestedNameSpecifier::Kind::Null:
+ llvm_unreachable("unexpected null nested name specifier");
+
+ case NestedNameSpecifier::Kind::Global:
Out << "gs";
// We want an 'sr' unless this is the entire NNS.
@@ -1373,27 +1381,29 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
// We never want an 'E' here.
return;
- case NestedNameSpecifier::Super:
+ case NestedNameSpecifier::Kind::MicrosoftSuper:
llvm_unreachable("Can't mangle __super specifier");
- case NestedNameSpecifier::Namespace:
- if (qualifier->getPrefix())
- mangleUnresolvedPrefix(qualifier->getPrefix(),
+ case NestedNameSpecifier::Kind::Namespace: {
+ auto [Namespace, Prefix] = Qualifier.getAsNamespaceAndPrefix();
+ if (Prefix)
+ mangleUnresolvedPrefix(Prefix,
/*recursive*/ true);
else
Out << "sr";
- mangleSourceNameWithAbiTags(qualifier->getAsNamespace());
+ mangleSourceNameWithAbiTags(Namespace);
break;
+ }
- case NestedNameSpecifier::TypeSpec: {
- const Type *type = qualifier->getAsType();
+ case NestedNameSpecifier::Kind::Type: {
+ const Type *type = Qualifier.getAsType();
// We only want to use an unresolved-type encoding if this is one of:
// - a decltype
// - a template type parameter
// - a template template parameter with arguments
// In all of these cases, we should have no prefix.
- if (NestedNameSpecifier *Prefix = qualifier->getPrefix()) {
+ if (NestedNameSpecifier Prefix = type->getPrefix()) {
mangleUnresolvedPrefix(Prefix,
/*recursive=*/true);
} else {
@@ -1406,18 +1416,6 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
break;
}
-
- case NestedNameSpecifier::Identifier:
- // Member expressions can have these without prefixes.
- if (qualifier->getPrefix())
- mangleUnresolvedPrefix(qualifier->getPrefix(),
- /*recursive*/ true);
- else
- Out << "sr";
-
- mangleSourceName(qualifier->getAsIdentifier());
- // An Identifier has no type information, so we can't emit abi tags for it.
- break;
}
// If this was the innermost part of the NNS, and we fell out to
@@ -1429,10 +1427,11 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
/// Mangle an unresolved-name, which is generally used for names which
/// weren't resolved to specific entities.
void CXXNameMangler::mangleUnresolvedName(
- NestedNameSpecifier *qualifier, DeclarationName name,
+ NestedNameSpecifier Qualifier, DeclarationName name,
const TemplateArgumentLoc *TemplateArgs, unsigned NumTemplateArgs,
unsigned knownArity) {
- if (qualifier) mangleUnresolvedPrefix(qualifier);
+ if (Qualifier)
+ mangleUnresolvedPrefix(Qualifier);
switch (name.getNameKind()) {
// <base-unresolved-name> ::= <simple-id>
case DeclarationName::Identifier:
@@ -1581,7 +1580,10 @@ void CXXNameMangler::mangleUnqualifiedName(
if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) {
// We must have an anonymous union or struct declaration.
- const RecordDecl *RD = VD->getType()->castAs<RecordType>()->getDecl();
+ const RecordDecl *RD = VD->getType()
+ ->castAs<RecordType>()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf();
// Itanium C++ ABI 5.1.2:
//
@@ -2167,49 +2169,22 @@ void CXXNameMangler::mangleLambdaSig(const CXXRecordDecl *Lambda) {
Lambda->getLambdaStaticInvoker());
}
-void CXXNameMangler::manglePrefix(NestedNameSpecifier *qualifier) {
- switch (qualifier->getKind()) {
- case NestedNameSpecifier::Global:
+void CXXNameMangler::manglePrefix(NestedNameSpecifier Qualifier) {
+ switch (Qualifier.getKind()) {
+ case NestedNameSpecifier::Kind::Null:
+ case NestedNameSpecifier::Kind::Global:
// nothing
return;
- case NestedNameSpecifier::Super:
+ case NestedNameSpecifier::Kind::MicrosoftSuper:
llvm_unreachable("Can't mangle __super specifier");
- case NestedNameSpecifier::Namespace:
- mangleName(qualifier->getAsNamespace()->getNamespace());
+ case NestedNameSpecifier::Kind::Namespace:
+ mangleName(Qualifier.getAsNamespaceAndPrefix().Namespace->getNamespace());
return;
- case NestedNameSpecifier::TypeSpec:
- if (NestedNameSpecifier *Prefix = qualifier->getPrefix()) {
- const auto *DTST =
- cast<DependentTemplateSpecializationType>(qualifier->getAsType());
- QualType NewT = getASTContext().getDependentTemplateSpecializationType(
- DTST->getKeyword(),
- {Prefix, DTST->getDependentTemplateName().getName(),
- /*HasTemplateKeyword=*/true},
- DTST->template_arguments(), /*IsCanonical=*/true);
- manglePrefix(NewT);
- return;
- }
- manglePrefix(QualType(qualifier->getAsType(), 0));
- return;
-
- case NestedNameSpecifier::Identifier:
- // Clang 14 and before did not consider this substitutable.
- bool Clang14Compat = isCompatibleWith(LangOptions::ClangABI::Ver14);
- if (!Clang14Compat && mangleSubstitution(qualifier))
- return;
-
- // Member expressions can have these without prefixes, but that
- // should end up in mangleUnresolvedPrefix instead.
- assert(qualifier->getPrefix());
- manglePrefix(qualifier->getPrefix());
-
- mangleSourceName(qualifier->getAsIdentifier());
-
- if (!Clang14Compat)
- addSubstitution(qualifier);
+ case NestedNameSpecifier::Kind::Type:
+ manglePrefix(QualType(Qualifier.getAsType(), 0));
return;
}
@@ -2269,8 +2244,7 @@ void CXXNameMangler::mangleTemplatePrefix(TemplateName Template) {
if (!Clang11Compat && mangleSubstitution(Template))
return;
- if (NestedNameSpecifier *Qualifier = Dependent->getQualifier())
- manglePrefix(Qualifier);
+ manglePrefix(Dependent->getQualifier());
if (Clang11Compat && mangleSubstitution(Template))
return;
@@ -2525,7 +2499,8 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty,
case Type::Enum:
case Type::Record:
- mangleSourceNameWithAbiTags(cast<TagType>(Ty)->getDecl());
+ mangleSourceNameWithAbiTags(
+ cast<TagType>(Ty)->getOriginalDecl()->getDefinitionOrSelf());
break;
case Type::TemplateSpecialization: {
@@ -2586,8 +2561,9 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty,
}
case Type::InjectedClassName:
- mangleSourceNameWithAbiTags(
- cast<InjectedClassNameType>(Ty)->getDecl());
+ mangleSourceNameWithAbiTags(cast<InjectedClassNameType>(Ty)
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf());
break;
case Type::DependentName:
@@ -2608,9 +2584,6 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty,
case Type::Using:
return mangleUnresolvedTypeOrSimpleId(cast<UsingType>(Ty)->desugar(),
Prefix);
- case Type::Elaborated:
- return mangleUnresolvedTypeOrSimpleId(
- cast<ElaboratedType>(Ty)->getNamedType(), Prefix);
}
return false;
@@ -3838,7 +3811,7 @@ void CXXNameMangler::mangleType(const RecordType *T) {
mangleType(static_cast<const TagType*>(T));
}
void CXXNameMangler::mangleType(const TagType *T) {
- mangleName(T->getDecl());
+ mangleName(T->getOriginalDecl()->getDefinitionOrSelf());
}
// <type> ::= <array-type>
@@ -3875,16 +3848,10 @@ void CXXNameMangler::mangleType(const IncompleteArrayType *T) {
// <pointer-to-member-type> ::= M <class type> <member type>
void CXXNameMangler::mangleType(const MemberPointerType *T) {
Out << 'M';
- if (auto *RD = T->getMostRecentCXXRecordDecl()) {
+ if (auto *RD = T->getMostRecentCXXRecordDecl())
mangleCXXRecordDecl(RD);
- } else {
- NestedNameSpecifier *NNS = T->getQualifier();
- if (auto *II = NNS->getAsIdentifier())
- mangleType(getASTContext().getDependentNameType(
- ElaboratedTypeKeyword::None, NNS->getPrefix(), II));
- else
- manglePrefix(NNS);
- }
+ else
+ mangleType(QualType(T->getQualifier().getAsType(), 0));
QualType PointeeType = T->getPointeeType();
if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(PointeeType)) {
mangleType(FPT);
@@ -4471,7 +4438,8 @@ void CXXNameMangler::mangleType(const InjectedClassNameType *T) {
// Mangle injected class name types as if the user had written the
// specialization out fully. It may not actually be possible to see
// this mangling, though.
- mangleType(T->getInjectedSpecializationType());
+ mangleType(T->getOriginalDecl()->getCanonicalTemplateSpecializationType(
+ getASTContext()));
}
void CXXNameMangler::mangleType(const TemplateSpecializationType *T) {
@@ -4747,7 +4715,7 @@ void CXXNameMangler::mangleIntegerLiteral(QualType T,
void CXXNameMangler::mangleMemberExprBase(const Expr *Base, bool IsArrow) {
// Ignore member expressions involving anonymous unions.
while (const auto *RT = Base->getType()->getAs<RecordType>()) {
- if (!RT->getDecl()->isAnonymousStructOrUnion())
+ if (!RT->getOriginalDecl()->isAnonymousStructOrUnion())
break;
const auto *ME = dyn_cast<MemberExpr>(Base);
if (!ME)
@@ -4768,9 +4736,8 @@ void CXXNameMangler::mangleMemberExprBase(const Expr *Base, bool IsArrow) {
}
/// Mangles a member expression.
-void CXXNameMangler::mangleMemberExpr(const Expr *base,
- bool isArrow,
- NestedNameSpecifier *qualifier,
+void CXXNameMangler::mangleMemberExpr(const Expr *base, bool isArrow,
+ NestedNameSpecifier Qualifier,
NamedDecl *firstQualifierLookup,
DeclarationName member,
const TemplateArgumentLoc *TemplateArgs,
@@ -4780,7 +4747,7 @@ void CXXNameMangler::mangleMemberExpr(const Expr *base,
// ::= pt <expression> <unresolved-name>
if (base)
mangleMemberExprBase(base, isArrow);
- mangleUnresolvedName(qualifier, member, TemplateArgs, NumTemplateArgs, arity);
+ mangleUnresolvedName(Qualifier, member, TemplateArgs, NumTemplateArgs, arity);
}
/// Look at the callee of the given call expression and determine if
@@ -5230,7 +5197,7 @@ recurse:
const auto *PDE = cast<CXXPseudoDestructorExpr>(E);
if (const Expr *Base = PDE->getBase())
mangleMemberExprBase(Base, PDE->isArrow());
- NestedNameSpecifier *Qualifier = PDE->getQualifier();
+ NestedNameSpecifier Qualifier = PDE->getQualifier();
if (TypeSourceInfo *ScopeInfo = PDE->getScopeTypeInfo()) {
if (Qualifier) {
mangleUnresolvedPrefix(Qualifier,
@@ -5855,7 +5822,8 @@ recurse:
// externally-visible declaration, so there's no standard mangling for
// this, but mangling as a literal of the closure type seems reasonable.
Out << "L";
- mangleType(Context.getASTContext().getRecordType(cast<LambdaExpr>(E)->getLambdaClass()));
+ mangleType(Context.getASTContext().getCanonicalTagType(
+ cast<LambdaExpr>(E)->getLambdaClass()));
Out << "E";
break;
}
@@ -6528,7 +6496,7 @@ static QualType getLValueType(ASTContext &Ctx, const APValue &LV) {
dyn_cast<FieldDecl>(E.getAsBaseOrMember().getPointer()))
T = FD->getType();
else
- T = Ctx.getRecordType(
+ T = Ctx.getCanonicalTagType(
cast<CXXRecordDecl>(E.getAsBaseOrMember().getPointer()));
}
return T;
@@ -6895,7 +6863,7 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V,
}
TypeSoFar = FD->getType();
} else {
- TypeSoFar = Ctx.getRecordType(cast<CXXRecordDecl>(D));
+ TypeSoFar = Ctx.getCanonicalTagType(cast<CXXRecordDecl>(D));
}
}
}
@@ -7005,14 +6973,6 @@ bool CXXNameMangler::mangleSubstitution(const NamedDecl *ND) {
return mangleSubstitution(reinterpret_cast<uintptr_t>(ND));
}
-bool CXXNameMangler::mangleSubstitution(NestedNameSpecifier *NNS) {
- assert(NNS->getKind() == NestedNameSpecifier::Identifier &&
- "mangleSubstitution(NestedNameSpecifier *) is only used for "
- "identifier nested name specifiers.");
- NNS = Context.getASTContext().getCanonicalNestedNameSpecifier(NNS);
- return mangleSubstitution(reinterpret_cast<uintptr_t>(NNS));
-}
-
/// Determine whether the given type has any qualifiers that are relevant for
/// substitutions.
static bool hasMangledSubstitutionQualifiers(QualType T) {
@@ -7023,7 +6983,7 @@ static bool hasMangledSubstitutionQualifiers(QualType T) {
bool CXXNameMangler::mangleSubstitution(QualType T) {
if (!hasMangledSubstitutionQualifiers(T)) {
if (const RecordType *RT = T->getAs<RecordType>())
- return mangleSubstitution(RT->getDecl());
+ return mangleSubstitution(RT->getOriginalDecl()->getDefinitionOrSelf());
}
uintptr_t TypePtr = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
@@ -7064,7 +7024,7 @@ bool CXXNameMangler::isSpecializedAs(QualType S, llvm::StringRef Name,
return false;
const ClassTemplateSpecializationDecl *SD =
- dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());
+ dyn_cast<ClassTemplateSpecializationDecl>(RT->getOriginalDecl());
if (!SD || !SD->getIdentifier()->isStr(Name))
return false;
@@ -7194,7 +7154,7 @@ bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) {
void CXXNameMangler::addSubstitution(QualType T) {
if (!hasMangledSubstitutionQualifiers(T)) {
if (const RecordType *RT = T->getAs<RecordType>()) {
- addSubstitution(RT->getDecl());
+ addSubstitution(RT->getOriginalDecl()->getDefinitionOrSelf());
return;
}
}
diff --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp
index 64ddb1e..b3f12a1 100644
--- a/clang/lib/AST/JSONNodeDumper.cpp
+++ b/clang/lib/AST/JSONNodeDumper.cpp
@@ -395,8 +395,8 @@ llvm::json::Array JSONNodeDumper::createCastPath(const CastExpr *C) {
for (auto I = C->path_begin(), E = C->path_end(); I != E; ++I) {
const CXXBaseSpecifier *Base = *I;
- const auto *RD =
- cast<CXXRecordDecl>(Base->getType()->castAs<RecordType>()->getDecl());
+ const auto *RD = cast<CXXRecordDecl>(
+ Base->getType()->castAs<RecordType>()->getOriginalDecl());
llvm::json::Object Val{{"name", RD->getName()}};
if (Base->isVirtual())
@@ -606,9 +606,8 @@ void JSONNodeDumper::VisitTypedefType(const TypedefType *TT) {
}
void JSONNodeDumper::VisitUsingType(const UsingType *TT) {
- JOS.attribute("decl", createBareDeclRef(TT->getFoundDecl()));
- if (!TT->typeMatchesDecl())
- JOS.attribute("type", createQualType(TT->desugar()));
+ JOS.attribute("decl", createBareDeclRef(TT->getDecl()));
+ JOS.attribute("type", createQualType(TT->desugar()));
}
void JSONNodeDumper::VisitFunctionType(const FunctionType *T) {
@@ -759,7 +758,15 @@ void JSONNodeDumper::VisitUnaryTransformType(const UnaryTransformType *UTT) {
}
void JSONNodeDumper::VisitTagType(const TagType *TT) {
- JOS.attribute("decl", createBareDeclRef(TT->getDecl()));
+ if (NestedNameSpecifier Qualifier = TT->getQualifier()) {
+ std::string Str;
+ llvm::raw_string_ostream OS(Str);
+ Qualifier.print(OS, PrintPolicy, /*ResolveTemplateArguments=*/true);
+ JOS.attribute("qualifier", Str);
+ }
+ JOS.attribute("decl", createBareDeclRef(TT->getOriginalDecl()));
+ if (TT->isTagOwned())
+ JOS.attribute("isTagOwned", true);
}
void JSONNodeDumper::VisitTemplateTypeParmType(
@@ -809,7 +816,7 @@ void JSONNodeDumper::VisitTemplateSpecializationType(
void JSONNodeDumper::VisitInjectedClassNameType(
const InjectedClassNameType *ICNT) {
- JOS.attribute("decl", createBareDeclRef(ICNT->getDecl()));
+ JOS.attribute("decl", createBareDeclRef(ICNT->getOriginalDecl()));
}
void JSONNodeDumper::VisitObjCInterfaceType(const ObjCInterfaceType *OIT) {
@@ -821,17 +828,6 @@ void JSONNodeDumper::VisitPackExpansionType(const PackExpansionType *PET) {
JOS.attribute("numExpansions", *N);
}
-void JSONNodeDumper::VisitElaboratedType(const ElaboratedType *ET) {
- if (const NestedNameSpecifier *NNS = ET->getQualifier()) {
- std::string Str;
- llvm::raw_string_ostream OS(Str);
- NNS->print(OS, PrintPolicy, /*ResolveTemplateArgs*/ true);
- JOS.attribute("qualifier", Str);
- }
- if (const TagDecl *TD = ET->getOwnedTagDecl())
- JOS.attribute("ownedTagDecl", createBareDeclRef(TD));
-}
-
void JSONNodeDumper::VisitMacroQualifiedType(const MacroQualifiedType *MQT) {
JOS.attribute("macroName", MQT->getMacroIdentifier()->getName());
}
@@ -902,9 +898,9 @@ void JSONNodeDumper::VisitNamespaceAliasDecl(const NamespaceAliasDecl *NAD) {
void JSONNodeDumper::VisitUsingDecl(const UsingDecl *UD) {
std::string Name;
- if (const NestedNameSpecifier *NNS = UD->getQualifier()) {
+ if (NestedNameSpecifier Qualifier = UD->getQualifier()) {
llvm::raw_string_ostream SOS(Name);
- NNS->print(SOS, UD->getASTContext().getPrintingPolicy());
+ Qualifier.print(SOS, UD->getASTContext().getPrintingPolicy());
}
Name += UD->getNameAsString();
JOS.attribute("name", Name);
diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp
index e6ea0ad..241c7c3 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -1805,17 +1805,16 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
case TemplateArgument::Declaration: {
const NamedDecl *ND = TA.getAsDecl();
if (isa<FieldDecl>(ND) || isa<IndirectFieldDecl>(ND)) {
- mangleMemberDataPointer(cast<CXXRecordDecl>(ND->getDeclContext())
- ->getMostRecentNonInjectedDecl(),
- cast<ValueDecl>(ND),
- cast<NonTypeTemplateParmDecl>(Parm),
- TA.getParamTypeForDecl());
+ mangleMemberDataPointer(
+ cast<CXXRecordDecl>(ND->getDeclContext())->getMostRecentDecl(),
+ cast<ValueDecl>(ND), cast<NonTypeTemplateParmDecl>(Parm),
+ TA.getParamTypeForDecl());
} else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD);
if (MD && MD->isInstance()) {
- mangleMemberFunctionPointer(
- MD->getParent()->getMostRecentNonInjectedDecl(), MD,
- cast<NonTypeTemplateParmDecl>(Parm), TA.getParamTypeForDecl());
+ mangleMemberFunctionPointer(MD->getParent()->getMostRecentDecl(), MD,
+ cast<NonTypeTemplateParmDecl>(Parm),
+ TA.getParamTypeForDecl());
} else {
mangleFunctionPointer(FD, cast<NonTypeTemplateParmDecl>(Parm),
TA.getParamTypeForDecl());
@@ -2021,7 +2020,7 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T,
if (RD->isAnonymousStructOrUnion())
continue;
} else {
- ET = getASTContext().getRecordType(cast<CXXRecordDecl>(D));
+ ET = getASTContext().getCanonicalTagType(cast<CXXRecordDecl>(D));
// Bug in MSVC: fully qualified name of base class should be used for
// mangling to prevent collisions e.g. on base classes with same names
// in different namespaces.
@@ -3247,11 +3246,11 @@ void MicrosoftCXXNameMangler::mangleTagTypeKind(TagTypeKind TTK) {
}
void MicrosoftCXXNameMangler::mangleType(const EnumType *T, Qualifiers,
SourceRange) {
- mangleType(cast<TagType>(T)->getDecl());
+ mangleType(cast<TagType>(T)->getOriginalDecl()->getDefinitionOrSelf());
}
void MicrosoftCXXNameMangler::mangleType(const RecordType *T, Qualifiers,
SourceRange) {
- mangleType(cast<TagType>(T)->getDecl());
+ mangleType(cast<TagType>(T)->getOriginalDecl()->getDefinitionOrSelf());
}
void MicrosoftCXXNameMangler::mangleType(const TagDecl *TD) {
mangleTagTypeKind(TD->getTagKind());
diff --git a/clang/lib/AST/NestedNameSpecifier.cpp b/clang/lib/AST/NestedNameSpecifier.cpp
index 56f74b9..c6af91f 100644
--- a/clang/lib/AST/NestedNameSpecifier.cpp
+++ b/clang/lib/AST/NestedNameSpecifier.cpp
@@ -15,7 +15,6 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
-#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DependenceFlags.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/TemplateName.h"
@@ -35,250 +34,67 @@
using namespace clang;
-NestedNameSpecifier *
-NestedNameSpecifier::FindOrInsert(const ASTContext &Context,
- const NestedNameSpecifier &Mockup) {
+const NamespaceAndPrefixStorage *
+NestedNameSpecifier::MakeNamespaceAndPrefixStorage(
+ const ASTContext &Ctx, const NamespaceBaseDecl *Namespace,
+ NestedNameSpecifier Prefix) {
llvm::FoldingSetNodeID ID;
- Mockup.Profile(ID);
+ NamespaceAndPrefixStorage::Profile(ID, Namespace, Prefix);
void *InsertPos = nullptr;
- NestedNameSpecifier *NNS
- = Context.NestedNameSpecifiers.FindNodeOrInsertPos(ID, InsertPos);
- if (!NNS) {
- NNS =
- new (Context, alignof(NestedNameSpecifier)) NestedNameSpecifier(Mockup);
- Context.NestedNameSpecifiers.InsertNode(NNS, InsertPos);
+ NamespaceAndPrefixStorage *S =
+ Ctx.NamespaceAndPrefixStorages.FindNodeOrInsertPos(ID, InsertPos);
+ if (!S) {
+ S = new (Ctx, alignof(NamespaceAndPrefixStorage))
+ NamespaceAndPrefixStorage(Namespace, Prefix);
+ Ctx.NamespaceAndPrefixStorages.InsertNode(S, InsertPos);
}
-
- return NNS;
-}
-
-NestedNameSpecifier *NestedNameSpecifier::Create(const ASTContext &Context,
- NestedNameSpecifier *Prefix,
- const IdentifierInfo *II) {
- assert(II && "Identifier cannot be NULL");
- assert((!Prefix || Prefix->isDependent()) && "Prefix must be dependent");
-
- NestedNameSpecifier Mockup;
- Mockup.Prefix.setPointer(Prefix);
- Mockup.Prefix.setInt(StoredIdentifier);
- Mockup.Specifier = const_cast<IdentifierInfo *>(II);
- return FindOrInsert(Context, Mockup);
-}
-
-NestedNameSpecifier *NestedNameSpecifier::Create(const ASTContext &Context,
- NestedNameSpecifier *Prefix,
- const NamespaceBaseDecl *NS) {
- assert(NS && "Namespace cannot be NULL");
- assert((!Prefix ||
- (Prefix->getAsType() == nullptr &&
- Prefix->getAsIdentifier() == nullptr)) &&
- "Broken nested name specifier");
- NestedNameSpecifier Mockup;
- Mockup.Prefix.setPointer(Prefix);
- Mockup.Prefix.setInt(StoredDecl);
- Mockup.Specifier = const_cast<NamespaceBaseDecl *>(NS);
- return FindOrInsert(Context, Mockup);
-}
-
-NestedNameSpecifier *NestedNameSpecifier::Create(const ASTContext &Context,
- NestedNameSpecifier *Prefix,
- const Type *T) {
- assert(T && "Type cannot be NULL");
- NestedNameSpecifier Mockup;
- Mockup.Prefix.setPointer(Prefix);
- Mockup.Prefix.setInt(StoredTypeSpec);
- Mockup.Specifier = const_cast<Type*>(T);
- return FindOrInsert(Context, Mockup);
-}
-
-NestedNameSpecifier *NestedNameSpecifier::Create(const ASTContext &Context,
- const IdentifierInfo *II) {
- assert(II && "Identifier cannot be NULL");
- NestedNameSpecifier Mockup;
- Mockup.Prefix.setPointer(nullptr);
- Mockup.Prefix.setInt(StoredIdentifier);
- Mockup.Specifier = const_cast<IdentifierInfo *>(II);
- return FindOrInsert(Context, Mockup);
-}
-
-NestedNameSpecifier *
-NestedNameSpecifier::GlobalSpecifier(const ASTContext &Context) {
- if (!Context.GlobalNestedNameSpecifier)
- Context.GlobalNestedNameSpecifier =
- new (Context, alignof(NestedNameSpecifier)) NestedNameSpecifier();
- return Context.GlobalNestedNameSpecifier;
-}
-
-NestedNameSpecifier *
-NestedNameSpecifier::SuperSpecifier(const ASTContext &Context,
- CXXRecordDecl *RD) {
- NestedNameSpecifier Mockup;
- Mockup.Prefix.setPointer(nullptr);
- Mockup.Prefix.setInt(StoredDecl);
- Mockup.Specifier = RD;
- return FindOrInsert(Context, Mockup);
+ return S;
}
-NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const {
- if (!Specifier)
- return Global;
-
- switch (Prefix.getInt()) {
- case StoredIdentifier:
- return Identifier;
-
- case StoredDecl: {
- NamedDecl *ND = static_cast<NamedDecl *>(Specifier);
- return isa<CXXRecordDecl>(ND) ? Super : Namespace;
- }
-
- case StoredTypeSpec:
- return TypeSpec;
- }
-
- llvm_unreachable("Invalid NNS Kind!");
-}
-
-/// Retrieve the namespace or namespace alias stored in this nested name
-/// specifier.
-NamespaceBaseDecl *NestedNameSpecifier::getAsNamespace() const {
- if (Prefix.getInt() == StoredDecl)
- return dyn_cast<NamespaceBaseDecl>(static_cast<NamedDecl *>(Specifier));
-
- return nullptr;
-}
-
-/// Retrieve the record declaration stored in this nested name specifier.
-CXXRecordDecl *NestedNameSpecifier::getAsRecordDecl() const {
- switch (Prefix.getInt()) {
- case StoredIdentifier:
- return nullptr;
-
- case StoredDecl:
- return dyn_cast<CXXRecordDecl>(static_cast<NamedDecl *>(Specifier));
-
- case StoredTypeSpec:
- return getAsType()->getAsCXXRecordDecl();
+bool NestedNameSpecifier::isFullyQualified() const {
+ switch (getKind()) {
+ case NestedNameSpecifier::Kind::Global:
+ return true;
+ case NestedNameSpecifier::Kind::Null:
+ case NestedNameSpecifier::Kind::MicrosoftSuper:
+ return false;
+ case NestedNameSpecifier::Kind::Namespace:
+ return getAsNamespaceAndPrefix().Prefix.isFullyQualified();
+ case NestedNameSpecifier::Kind::Type:
+ return getAsType()->getPrefix().isFullyQualified();
}
-
llvm_unreachable("Invalid NNS Kind!");
}
NestedNameSpecifierDependence NestedNameSpecifier::getDependence() const {
switch (getKind()) {
- case Identifier: {
- // Identifier specifiers always represent dependent types
- auto F = NestedNameSpecifierDependence::Dependent |
- NestedNameSpecifierDependence::Instantiation;
- // Prefix can contain unexpanded template parameters.
- if (getPrefix())
- return F | getPrefix()->getDependence();
- return F;
- }
-
- case Namespace:
- case Global:
- return NestedNameSpecifierDependence::None;
-
- case Super: {
- CXXRecordDecl *RD = static_cast<CXXRecordDecl *>(Specifier);
- for (const auto &Base : RD->bases())
- if (Base.getType()->isDependentType())
- // FIXME: must also be instantiation-dependent.
- return NestedNameSpecifierDependence::Dependent;
+ case Kind::Null:
+ case Kind::Global:
+ case Kind::Namespace:
return NestedNameSpecifierDependence::None;
+ case Kind::MicrosoftSuper: {
+ CXXRecordDecl *RD = getAsMicrosoftSuper();
+ return RD->isDependentContext()
+ ? NestedNameSpecifierDependence::DependentInstantiation |
+ NestedNameSpecifierDependence::Dependent
+ : NestedNameSpecifierDependence::None;
}
-
- case TypeSpec: {
- NestedNameSpecifierDependence Dep =
- toNestedNameSpecifierDependendence(getAsType()->getDependence());
- if (NestedNameSpecifier *Prefix = getPrefix())
- Dep |=
- Prefix->getDependence() & ~NestedNameSpecifierDependence::Dependent;
- return Dep;
- }
+ case Kind::Type:
+ return toNestedNameSpecifierDependence(getAsType()->getDependence());
}
llvm_unreachable("Invalid NNS Kind!");
}
-bool NestedNameSpecifier::isDependent() const {
- return getDependence() & NestedNameSpecifierDependence::Dependent;
-}
-
-bool NestedNameSpecifier::isInstantiationDependent() const {
- return getDependence() & NestedNameSpecifierDependence::Instantiation;
-}
-
-bool NestedNameSpecifier::containsUnexpandedParameterPack() const {
- return getDependence() & NestedNameSpecifierDependence::UnexpandedPack;
-}
-
-bool NestedNameSpecifier::containsErrors() const {
- return getDependence() & NestedNameSpecifierDependence::Error;
-}
-
-const Type *
-NestedNameSpecifier::translateToType(const ASTContext &Context) const {
- NestedNameSpecifier *Prefix = getPrefix();
- switch (getKind()) {
- case SpecifierKind::Identifier:
- return Context
- .getDependentNameType(ElaboratedTypeKeyword::None, Prefix,
- getAsIdentifier())
- .getTypePtr();
- case SpecifierKind::TypeSpec: {
- const Type *T = getAsType();
- switch (T->getTypeClass()) {
- case Type::DependentTemplateSpecialization: {
- const auto *DT = cast<DependentTemplateSpecializationType>(T);
- const DependentTemplateStorage &DTN = DT->getDependentTemplateName();
- return Context
- .getDependentTemplateSpecializationType(
- ElaboratedTypeKeyword::None,
- {Prefix, DTN.getName(), DTN.hasTemplateKeyword()},
- DT->template_arguments())
- .getTypePtr();
- }
- case Type::Record:
- case Type::TemplateSpecialization:
- case Type::Using:
- case Type::Enum:
- case Type::Typedef:
- case Type::UnresolvedUsing:
- return Context
- .getElaboratedType(ElaboratedTypeKeyword::None, Prefix,
- QualType(T, 0))
- .getTypePtr();
- default:
- assert(Prefix == nullptr && "unexpected type with elaboration");
- return T;
- }
- }
- case SpecifierKind::Global:
- case SpecifierKind::Namespace:
- case SpecifierKind::Super:
- // These are not representable as types.
- return nullptr;
- }
- llvm_unreachable("Unhandled SpecifierKind enum");
-}
-
/// Print this nested name specifier to the given output
/// stream.
void NestedNameSpecifier::print(raw_ostream &OS, const PrintingPolicy &Policy,
bool ResolveTemplateArguments,
bool PrintFinalScopeResOp) const {
- if (getPrefix())
- getPrefix()->print(OS, Policy);
-
switch (getKind()) {
- case Identifier:
- OS << getAsIdentifier()->getName();
- break;
-
- case Namespace: {
- NamespaceBaseDecl *Namespace = getAsNamespace();
+ case Kind::Namespace: {
+ auto [Namespace, Prefix] = getAsNamespaceAndPrefix();
+ Prefix.print(OS, Policy);
if (const auto *NS = dyn_cast<NamespaceDecl>(Namespace)) {
assert(!NS->isAnonymousNamespace());
OS << NS->getName();
@@ -287,134 +103,49 @@ void NestedNameSpecifier::print(raw_ostream &OS, const PrintingPolicy &Policy,
}
break;
}
-
- case Global:
+ case Kind::Global:
OS << "::";
return;
-
- case Super:
+ case Kind::MicrosoftSuper:
OS << "__super";
break;
-
- case TypeSpec: {
+ case Kind::Type: {
PrintingPolicy InnerPolicy(Policy);
- InnerPolicy.SuppressScope = true;
InnerPolicy.SuppressTagKeyword = true;
QualType(getAsType(), 0).print(OS, InnerPolicy);
break;
}
+ case Kind::Null:
+ return;
}
-
if (PrintFinalScopeResOp)
OS << "::";
}
-LLVM_DUMP_METHOD void NestedNameSpecifier::dump(const LangOptions &LO) const {
- dump(llvm::errs(), LO);
+LLVM_DUMP_METHOD void NestedNameSpecifier::dump(llvm::raw_ostream *OS,
+ const LangOptions *LO) const {
+ print(OS ? *OS : llvm::errs(), LO ? *LO : LangOptions());
}
-LLVM_DUMP_METHOD void NestedNameSpecifier::dump() const { dump(llvm::errs()); }
-
+LLVM_DUMP_METHOD void NestedNameSpecifier::dump(const LangOptions &LO) const {
+ dump(/*OS=*/nullptr, &LO);
+}
LLVM_DUMP_METHOD void NestedNameSpecifier::dump(llvm::raw_ostream &OS) const {
- LangOptions LO;
- dump(OS, LO);
+ dump(&OS);
}
-
LLVM_DUMP_METHOD void NestedNameSpecifier::dump(llvm::raw_ostream &OS,
const LangOptions &LO) const {
- print(OS, PrintingPolicy(LO));
-}
-
-unsigned
-NestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier *Qualifier) {
- assert(Qualifier && "Expected a non-NULL qualifier");
-
- // Location of the trailing '::'.
- unsigned Length = sizeof(SourceLocation::UIntTy);
-
- switch (Qualifier->getKind()) {
- case NestedNameSpecifier::Global:
- // Nothing more to add.
- break;
-
- case NestedNameSpecifier::Identifier:
- case NestedNameSpecifier::Namespace:
- case NestedNameSpecifier::Super:
- // The location of the identifier or namespace name.
- Length += sizeof(SourceLocation::UIntTy);
- break;
-
- case NestedNameSpecifier::TypeSpec:
- // The "void*" that points at the TypeLoc data.
- // Note: the 'template' keyword is part of the TypeLoc.
- Length += sizeof(void *);
- break;
- }
-
- return Length;
-}
-
-unsigned
-NestedNameSpecifierLoc::getDataLength(NestedNameSpecifier *Qualifier) {
- unsigned Length = 0;
- for (; Qualifier; Qualifier = Qualifier->getPrefix())
- Length += getLocalDataLength(Qualifier);
- return Length;
-}
-
-/// Load a (possibly unaligned) source location from a given address
-/// and offset.
-static SourceLocation LoadSourceLocation(void *Data, unsigned Offset) {
- SourceLocation::UIntTy Raw;
- memcpy(&Raw, static_cast<char *>(Data) + Offset, sizeof(Raw));
- return SourceLocation::getFromRawEncoding(Raw);
+ dump(&OS, &LO);
}
-/// Load a (possibly unaligned) pointer from a given address and
-/// offset.
-static void *LoadPointer(void *Data, unsigned Offset) {
- void *Result;
- memcpy(&Result, static_cast<char *>(Data) + Offset, sizeof(void*));
- return Result;
-}
-
-SourceRange NestedNameSpecifierLoc::getLocalSourceRange() const {
+SourceLocation NestedNameSpecifierLoc::getBeginLoc() const {
if (!Qualifier)
- return SourceRange();
-
- unsigned Offset = getDataLength(Qualifier->getPrefix());
- switch (Qualifier->getKind()) {
- case NestedNameSpecifier::Global:
- return LoadSourceLocation(Data, Offset);
-
- case NestedNameSpecifier::Identifier:
- case NestedNameSpecifier::Namespace:
- case NestedNameSpecifier::Super:
- return SourceRange(
- LoadSourceLocation(Data, Offset),
- LoadSourceLocation(Data, Offset + sizeof(SourceLocation::UIntTy)));
-
- case NestedNameSpecifier::TypeSpec: {
- // The "void*" that points at the TypeLoc data.
- // Note: the 'template' keyword is part of the TypeLoc.
- void *TypeData = LoadPointer(Data, Offset);
- TypeLoc TL(Qualifier->getAsType(), TypeData);
- return SourceRange(TL.getBeginLoc(),
- LoadSourceLocation(Data, Offset + sizeof(void*)));
- }
- }
+ return SourceLocation();
- llvm_unreachable("Invalid NNS Kind!");
-}
-
-TypeLoc NestedNameSpecifierLoc::getTypeLoc() const {
- if (Qualifier->getKind() != NestedNameSpecifier::TypeSpec)
- return TypeLoc();
-
- // The "void*" that points at the TypeLoc data.
- unsigned Offset = getDataLength(Qualifier->getPrefix());
- void *TypeData = LoadPointer(Data, Offset);
- return TypeLoc(Qualifier->getAsType(), TypeData);
+ NestedNameSpecifierLoc First = *this;
+ while (NestedNameSpecifierLoc Prefix = First.getAsNamespaceAndPrefix().Prefix)
+ First = Prefix;
+ return First.getLocalSourceRange().getBegin();
}
static void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize,
@@ -516,10 +247,10 @@ operator=(const NestedNameSpecifierLocBuilder &Other) {
return *this;
}
-void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, TypeLoc TL,
- SourceLocation ColonColonLoc) {
- Representation =
- NestedNameSpecifier::Create(Context, Representation, TL.getTypePtr());
+void NestedNameSpecifierLocBuilder::Make(ASTContext &Context, TypeLoc TL,
+ SourceLocation ColonColonLoc) {
+ assert(!Representation);
+ Representation = NestedNameSpecifier(TL.getTypePtr());
// Push source-location info into the buffer.
SavePointer(TL.getOpaqueData(), Buffer, BufferSize, BufferCapacity);
@@ -527,23 +258,10 @@ void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, TypeLoc TL,
}
void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
- IdentifierInfo *Identifier,
- SourceLocation IdentifierLoc,
- SourceLocation ColonColonLoc) {
- Representation = NestedNameSpecifier::Create(Context, Representation,
- Identifier);
-
- // Push source-location info into the buffer.
- SaveSourceLocation(IdentifierLoc, Buffer, BufferSize, BufferCapacity);
- SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
-}
-
-void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
- NamespaceBaseDecl *Namespace,
+ const NamespaceBaseDecl *Namespace,
SourceLocation NamespaceLoc,
SourceLocation ColonColonLoc) {
- Representation = NestedNameSpecifier::Create(Context, Representation,
- Namespace);
+ Representation = NestedNameSpecifier(Context, Namespace, Representation);
// Push source-location info into the buffer.
SaveSourceLocation(NamespaceLoc, Buffer, BufferSize, BufferCapacity);
@@ -553,60 +271,48 @@ void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
void NestedNameSpecifierLocBuilder::MakeGlobal(ASTContext &Context,
SourceLocation ColonColonLoc) {
assert(!Representation && "Already have a nested-name-specifier!?");
- Representation = NestedNameSpecifier::GlobalSpecifier(Context);
+ Representation = NestedNameSpecifier::getGlobal();
// Push source-location info into the buffer.
SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
}
-void NestedNameSpecifierLocBuilder::MakeSuper(ASTContext &Context,
- CXXRecordDecl *RD,
- SourceLocation SuperLoc,
- SourceLocation ColonColonLoc) {
- Representation = NestedNameSpecifier::SuperSpecifier(Context, RD);
+void NestedNameSpecifierLocBuilder::MakeMicrosoftSuper(
+ ASTContext &Context, CXXRecordDecl *RD, SourceLocation SuperLoc,
+ SourceLocation ColonColonLoc) {
+ Representation = NestedNameSpecifier(RD);
// Push source-location info into the buffer.
SaveSourceLocation(SuperLoc, Buffer, BufferSize, BufferCapacity);
SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
}
-void NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context,
- NestedNameSpecifier *Qualifier,
+void NestedNameSpecifierLocBuilder::PushTrivial(ASTContext &Context,
+ NestedNameSpecifier Qualifier,
SourceRange R) {
- Representation = Qualifier;
-
// Construct bogus (but well-formed) source information for the
// nested-name-specifier.
- BufferSize = 0;
- SmallVector<NestedNameSpecifier *, 4> Stack;
- for (NestedNameSpecifier *NNS = Qualifier; NNS; NNS = NNS->getPrefix())
- Stack.push_back(NNS);
- while (!Stack.empty()) {
- NestedNameSpecifier *NNS = Stack.pop_back_val();
- switch (NNS->getKind()) {
- case NestedNameSpecifier::Identifier:
- case NestedNameSpecifier::Namespace:
- SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity);
- break;
-
- case NestedNameSpecifier::TypeSpec: {
- TypeSourceInfo *TSInfo
- = Context.getTrivialTypeSourceInfo(QualType(NNS->getAsType(), 0),
- R.getBegin());
- SavePointer(TSInfo->getTypeLoc().getOpaqueData(), Buffer, BufferSize,
- BufferCapacity);
- break;
- }
-
- case NestedNameSpecifier::Global:
- case NestedNameSpecifier::Super:
- break;
- }
-
- // Save the location of the '::'.
- SaveSourceLocation(Stack.empty()? R.getEnd() : R.getBegin(),
- Buffer, BufferSize, BufferCapacity);
+ switch (Qualifier.getKind()) {
+ case NestedNameSpecifier::Kind::Null:
+ return;
+ case NestedNameSpecifier::Kind::Namespace: {
+ auto [_1, Prefix] = Qualifier.getAsNamespaceAndPrefix();
+ PushTrivial(Context, Prefix, R.getBegin());
+ SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity);
+ break;
+ }
+ case NestedNameSpecifier::Kind::Type: {
+ TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(
+ QualType(Qualifier.getAsType(), 0), R.getBegin());
+ SavePointer(TSInfo->getTypeLoc().getOpaqueData(), Buffer, BufferSize,
+ BufferCapacity);
+ break;
+ }
+ case NestedNameSpecifier::Kind::Global:
+ case NestedNameSpecifier::Kind::MicrosoftSuper:
+ break;
}
+ SaveSourceLocation(R.getEnd(), Buffer, BufferSize, BufferCapacity);
}
void NestedNameSpecifierLocBuilder::Adopt(NestedNameSpecifierLoc Other) {
@@ -614,7 +320,7 @@ void NestedNameSpecifierLocBuilder::Adopt(NestedNameSpecifierLoc Other) {
free(Buffer);
if (!Other) {
- Representation = nullptr;
+ Representation = std::nullopt;
BufferSize = 0;
return;
}
diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp
index bd87d44..fb95f58 100644
--- a/clang/lib/AST/ODRHash.cpp
+++ b/clang/lib/AST/ODRHash.cpp
@@ -111,34 +111,28 @@ void ODRHash::AddDeclarationNameInfoImpl(DeclarationNameInfo NameInfo) {
}
}
-void ODRHash::AddNestedNameSpecifier(const NestedNameSpecifier *NNS) {
- assert(NNS && "Expecting non-null pointer.");
- const auto *Prefix = NNS->getPrefix();
- AddBoolean(Prefix);
- if (Prefix) {
- AddNestedNameSpecifier(Prefix);
- }
- auto Kind = NNS->getKind();
- ID.AddInteger(Kind);
+void ODRHash::AddNestedNameSpecifier(NestedNameSpecifier NNS) {
+ auto Kind = NNS.getKind();
+ ID.AddInteger(llvm::to_underlying(Kind));
switch (Kind) {
- case NestedNameSpecifier::Identifier:
- AddIdentifierInfo(NNS->getAsIdentifier());
- break;
- case NestedNameSpecifier::Namespace:
- AddDecl(NNS->getAsNamespace());
+ case NestedNameSpecifier::Kind::Namespace: {
+ auto [Namespace, Prefix] = NNS.getAsNamespaceAndPrefix();
+ AddDecl(Namespace);
+ AddNestedNameSpecifier(Prefix);
break;
- case NestedNameSpecifier::TypeSpec:
- AddType(NNS->getAsType());
+ }
+ case NestedNameSpecifier::Kind::Type:
+ AddType(NNS.getAsType());
break;
- case NestedNameSpecifier::Global:
- case NestedNameSpecifier::Super:
+ case NestedNameSpecifier::Kind::Null:
+ case NestedNameSpecifier::Kind::Global:
+ case NestedNameSpecifier::Kind::MicrosoftSuper:
break;
}
}
void ODRHash::AddDependentTemplateName(const DependentTemplateStorage &Name) {
- if (NestedNameSpecifier *NNS = Name.getQualifier())
- AddNestedNameSpecifier(NNS);
+ AddNestedNameSpecifier(Name.getQualifier());
if (IdentifierOrOverloadedOperator IO = Name.getName();
const IdentifierInfo *II = IO.getIdentifier())
AddIdentifierInfo(II);
@@ -156,8 +150,7 @@ void ODRHash::AddTemplateName(TemplateName Name) {
break;
case TemplateName::QualifiedTemplate: {
QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName();
- if (NestedNameSpecifier *NNS = QTN->getQualifier())
- AddNestedNameSpecifier(NNS);
+ AddNestedNameSpecifier(QTN->getQualifier());
AddBoolean(QTN->hasTemplateKeyword());
AddTemplateName(QTN->getUnderlyingTemplate());
break;
@@ -889,11 +882,8 @@ public:
}
}
- void AddNestedNameSpecifier(const NestedNameSpecifier *NNS) {
- Hash.AddBoolean(NNS);
- if (NNS) {
- Hash.AddNestedNameSpecifier(NNS);
- }
+ void AddNestedNameSpecifier(NestedNameSpecifier NNS) {
+ Hash.AddNestedNameSpecifier(NNS);
}
void AddIdentifierInfo(const IdentifierInfo *II) {
@@ -907,52 +897,33 @@ public:
ID.AddInteger(Quals.getAsOpaqueValue());
}
- // Return the RecordType if the typedef only strips away a keyword.
- // Otherwise, return the original type.
- static const Type *RemoveTypedef(const Type *T) {
+ // Handle typedefs which only strip away a keyword.
+ bool handleTypedef(const Type *T) {
const auto *TypedefT = dyn_cast<TypedefType>(T);
- if (!TypedefT) {
- return T;
- }
-
- const TypedefNameDecl *D = TypedefT->getDecl();
- QualType UnderlyingType = D->getUnderlyingType();
-
- if (UnderlyingType.hasLocalQualifiers()) {
- return T;
- }
-
- const auto *ElaboratedT = dyn_cast<ElaboratedType>(UnderlyingType);
- if (!ElaboratedT) {
- return T;
- }
+ if (!TypedefT)
+ return false;
- if (ElaboratedT->getQualifier() != nullptr) {
- return T;
- }
+ QualType UnderlyingType = TypedefT->desugar();
- QualType NamedType = ElaboratedT->getNamedType();
- if (NamedType.hasLocalQualifiers()) {
- return T;
- }
+ if (UnderlyingType.hasLocalQualifiers())
+ return false;
- const auto *RecordT = dyn_cast<RecordType>(NamedType);
- if (!RecordT) {
- return T;
- }
+ const auto *TagT = dyn_cast<TagType>(UnderlyingType);
+ if (!TagT || TagT->getQualifier())
+ return false;
- const IdentifierInfo *TypedefII = TypedefT->getDecl()->getIdentifier();
- const IdentifierInfo *RecordII = RecordT->getDecl()->getIdentifier();
- if (!TypedefII || !RecordII ||
- TypedefII->getName() != RecordII->getName()) {
- return T;
- }
+ if (TypedefT->getDecl()->getIdentifier() !=
+ TagT->getOriginalDecl()->getIdentifier())
+ return false;
- return RecordT;
+ ID.AddInteger(TagT->getTypeClass());
+ VisitTagType(TagT, /*ElaboratedOverride=*/TypedefT);
+ return true;
}
void Visit(const Type *T) {
- T = RemoveTypedef(T);
+ if (handleTypedef(T))
+ return;
ID.AddInteger(T->getTypeClass());
Inherited::Visit(T);
}
@@ -1088,7 +1059,7 @@ public:
}
void VisitInjectedClassNameType(const InjectedClassNameType *T) {
- AddDecl(T->getDecl());
+ AddDecl(T->getOriginalDecl()->getDefinitionOrSelf());
VisitType(T);
}
@@ -1186,14 +1157,17 @@ public:
VisitType(T);
}
- void VisitTagType(const TagType *T) {
- AddDecl(T->getDecl());
+ void VisitTagType(const TagType *T,
+ const TypedefType *ElaboratedOverride = nullptr) {
+ ID.AddInteger(llvm::to_underlying(
+ ElaboratedOverride ? ElaboratedTypeKeyword::None : T->getKeyword()));
+ AddNestedNameSpecifier(ElaboratedOverride
+ ? ElaboratedOverride->getQualifier()
+ : T->getQualifier());
+ AddDecl(T->getOriginalDecl()->getDefinitionOrSelf());
VisitType(T);
}
- void VisitRecordType(const RecordType *T) { VisitTagType(T); }
- void VisitEnumType(const EnumType *T) { VisitTagType(T); }
-
void VisitTemplateSpecializationType(const TemplateSpecializationType *T) {
ID.AddInteger(T->template_arguments().size());
for (const auto &TA : T->template_arguments()) {
@@ -1211,6 +1185,8 @@ public:
}
void VisitTypedefType(const TypedefType *T) {
+ ID.AddInteger(llvm::to_underlying(T->getKeyword()));
+ AddNestedNameSpecifier(T->getQualifier());
AddDecl(T->getDecl());
VisitType(T);
}
@@ -1247,12 +1223,6 @@ public:
VisitTypeWithKeyword(T);
}
- void VisitElaboratedType(const ElaboratedType *T) {
- AddNestedNameSpecifier(T->getQualifier());
- AddQualType(T->getNamedType());
- VisitTypeWithKeyword(T);
- }
-
void VisitUnaryTransformType(const UnaryTransformType *T) {
AddQualType(T->getUnderlyingType());
AddQualType(T->getBaseType());
@@ -1330,7 +1300,7 @@ void ODRHash::AddStructuralValue(const APValue &Value) {
TypeSoFar = FD->getType();
} else {
TypeSoFar =
- D->getASTContext().getRecordType(cast<CXXRecordDecl>(D));
+ D->getASTContext().getCanonicalTagType(cast<CXXRecordDecl>(D));
}
}
}
diff --git a/clang/lib/AST/OpenACCClause.cpp b/clang/lib/AST/OpenACCClause.cpp
index f7a98bd..fe20004 100644
--- a/clang/lib/AST/OpenACCClause.cpp
+++ b/clang/lib/AST/OpenACCClause.cpp
@@ -329,10 +329,11 @@ OpenACCPrivateClause::Create(const ASTContext &C, SourceLocation BeginLoc,
OpenACCFirstPrivateClause *OpenACCFirstPrivateClause::Create(
const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
- ArrayRef<Expr *> VarList, ArrayRef<VarDecl *> InitRecipes,
+ ArrayRef<Expr *> VarList, ArrayRef<OpenACCFirstPrivateRecipe> InitRecipes,
SourceLocation EndLoc) {
- void *Mem =
- C.Allocate(OpenACCFirstPrivateClause::totalSizeToAlloc<Expr *, VarDecl *>(
+ void *Mem = C.Allocate(
+ OpenACCFirstPrivateClause::totalSizeToAlloc<Expr *,
+ OpenACCFirstPrivateRecipe>(
VarList.size(), InitRecipes.size()));
return new (Mem) OpenACCFirstPrivateClause(BeginLoc, LParenLoc, VarList,
InitRecipes, EndLoc);
diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp
index de8b599..588b0dc 100644
--- a/clang/lib/AST/OpenMPClause.cpp
+++ b/clang/lib/AST/OpenMPClause.cpp
@@ -2350,17 +2350,16 @@ void OMPClausePrinter::VisitOMPReductionClause(OMPReductionClause *Node) {
if (Node->getModifierLoc().isValid())
OS << getOpenMPSimpleClauseTypeName(OMPC_reduction, Node->getModifier())
<< ", ";
- NestedNameSpecifier *QualifierLoc =
+ NestedNameSpecifier Qualifier =
Node->getQualifierLoc().getNestedNameSpecifier();
OverloadedOperatorKind OOK =
Node->getNameInfo().getName().getCXXOverloadedOperator();
- if (QualifierLoc == nullptr && OOK != OO_None) {
+ if (!Qualifier && OOK != OO_None) {
// Print reduction identifier in C format
OS << getOperatorSpelling(OOK);
} else {
// Use C++ format
- if (QualifierLoc != nullptr)
- QualifierLoc->print(OS, Policy);
+ Qualifier.print(OS, Policy);
OS << Node->getNameInfo();
}
OS << ":";
@@ -2373,17 +2372,16 @@ void OMPClausePrinter::VisitOMPTaskReductionClause(
OMPTaskReductionClause *Node) {
if (!Node->varlist_empty()) {
OS << "task_reduction(";
- NestedNameSpecifier *QualifierLoc =
+ NestedNameSpecifier Qualifier =
Node->getQualifierLoc().getNestedNameSpecifier();
OverloadedOperatorKind OOK =
Node->getNameInfo().getName().getCXXOverloadedOperator();
- if (QualifierLoc == nullptr && OOK != OO_None) {
+ if (!Qualifier && OOK != OO_None) {
// Print reduction identifier in C format
OS << getOperatorSpelling(OOK);
} else {
// Use C++ format
- if (QualifierLoc != nullptr)
- QualifierLoc->print(OS, Policy);
+ Qualifier.print(OS, Policy);
OS << Node->getNameInfo();
}
OS << ":";
@@ -2395,17 +2393,16 @@ void OMPClausePrinter::VisitOMPTaskReductionClause(
void OMPClausePrinter::VisitOMPInReductionClause(OMPInReductionClause *Node) {
if (!Node->varlist_empty()) {
OS << "in_reduction(";
- NestedNameSpecifier *QualifierLoc =
+ NestedNameSpecifier Qualifier =
Node->getQualifierLoc().getNestedNameSpecifier();
OverloadedOperatorKind OOK =
Node->getNameInfo().getName().getCXXOverloadedOperator();
- if (QualifierLoc == nullptr && OOK != OO_None) {
+ if (!Qualifier && OOK != OO_None) {
// Print reduction identifier in C format
OS << getOperatorSpelling(OOK);
} else {
// Use C++ format
- if (QualifierLoc != nullptr)
- QualifierLoc->print(OS, Policy);
+ Qualifier.print(OS, Policy);
OS << Node->getNameInfo();
}
OS << ":";
@@ -2508,10 +2505,9 @@ template <typename T>
static void PrintMapper(raw_ostream &OS, T *Node,
const PrintingPolicy &Policy) {
OS << '(';
- NestedNameSpecifier *MapperNNS =
+ NestedNameSpecifier MapperNNS =
Node->getMapperQualifierLoc().getNestedNameSpecifier();
- if (MapperNNS)
- MapperNNS->print(OS, Policy);
+ MapperNNS.print(OS, Policy);
OS << Node->getMapperIdInfo() << ')';
}
diff --git a/clang/lib/AST/ParentMapContext.cpp b/clang/lib/AST/ParentMapContext.cpp
index 68dfe4d..acc011c 100644
--- a/clang/lib/AST/ParentMapContext.cpp
+++ b/clang/lib/AST/ParentMapContext.cpp
@@ -438,10 +438,12 @@ private:
DeclNode, DeclNode, [&] { return VisitorBase::TraverseDecl(DeclNode); },
&Map.PointerParents);
}
- bool TraverseTypeLoc(TypeLoc TypeLocNode) {
+ bool TraverseTypeLoc(TypeLoc TypeLocNode, bool TraverseQualifier = true) {
return TraverseNode(
TypeLocNode, DynTypedNode::create(TypeLocNode),
- [&] { return VisitorBase::TraverseTypeLoc(TypeLocNode); },
+ [&] {
+ return VisitorBase::TraverseTypeLoc(TypeLocNode, TraverseQualifier);
+ },
&Map.OtherParents);
}
bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSLocNode) {
diff --git a/clang/lib/AST/PrintfFormatString.cpp b/clang/lib/AST/PrintfFormatString.cpp
index bcd44f0..687160c 100644
--- a/clang/lib/AST/PrintfFormatString.cpp
+++ b/clang/lib/AST/PrintfFormatString.cpp
@@ -794,7 +794,7 @@ bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
// If it's an enum, get its underlying type.
if (const EnumType *ETy = QT->getAs<EnumType>())
- QT = ETy->getDecl()->getIntegerType();
+ QT = ETy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
const BuiltinType *BT = QT->getAs<BuiltinType>();
if (!BT) {
diff --git a/clang/lib/AST/QualTypeNames.cpp b/clang/lib/AST/QualTypeNames.cpp
index 9731b3a..ee7fec3 100644
--- a/clang/lib/AST/QualTypeNames.cpp
+++ b/clang/lib/AST/QualTypeNames.cpp
@@ -24,10 +24,9 @@ namespace TypeName {
/// is requested.
/// \param[in] WithGlobalNsPrefix - Indicate whether the global namespace
/// specifier "::" should be prepended or not.
-static NestedNameSpecifier *createNestedNameSpecifier(
- const ASTContext &Ctx,
- const NamespaceDecl *Namesp,
- bool WithGlobalNsPrefix);
+static NestedNameSpecifier
+createNestedNameSpecifier(const ASTContext &Ctx, const NamespaceDecl *Namesp,
+ bool WithGlobalNsPrefix);
/// Create a NestedNameSpecifier for TagDecl and its enclosing
/// scopes.
@@ -39,22 +38,24 @@ static NestedNameSpecifier *createNestedNameSpecifier(
/// qualified names.
/// \param[in] WithGlobalNsPrefix - Indicate whether the global namespace
/// specifier "::" should be prepended or not.
-static NestedNameSpecifier *createNestedNameSpecifier(
- const ASTContext &Ctx, const TypeDecl *TD,
- bool FullyQualify, bool WithGlobalNsPrefix);
+static NestedNameSpecifier createNestedNameSpecifier(const ASTContext &Ctx,
+ const TypeDecl *TD,
+ bool FullyQualify,
+ bool WithGlobalNsPrefix);
-static NestedNameSpecifier *createNestedNameSpecifierForScopeOf(
- const ASTContext &Ctx, const Decl *decl,
- bool FullyQualified, bool WithGlobalNsPrefix);
+static NestedNameSpecifier
+createNestedNameSpecifierForScopeOf(const ASTContext &Ctx, const Decl *decl,
+ bool FullyQualified,
+ bool WithGlobalNsPrefix);
-static NestedNameSpecifier *getFullyQualifiedNestedNameSpecifier(
- const ASTContext &Ctx, NestedNameSpecifier *scope, bool WithGlobalNsPrefix);
+static NestedNameSpecifier getFullyQualifiedNestedNameSpecifier(
+ const ASTContext &Ctx, NestedNameSpecifier NNS, bool WithGlobalNsPrefix);
static bool getFullyQualifiedTemplateName(const ASTContext &Ctx,
TemplateName &TName,
bool WithGlobalNsPrefix) {
bool Changed = false;
- NestedNameSpecifier *NNS = nullptr;
+ NestedNameSpecifier NNS = std::nullopt;
TemplateDecl *ArgTDecl = TName.getAsTemplateDecl();
// ArgTDecl won't be NULL because we asserted that this isn't a
@@ -65,13 +66,13 @@ static bool getFullyQualifiedTemplateName(const ASTContext &Ctx,
if (QTName &&
!QTName->hasTemplateKeyword() &&
(NNS = QTName->getQualifier())) {
- NestedNameSpecifier *QNNS = getFullyQualifiedNestedNameSpecifier(
- Ctx, NNS, WithGlobalNsPrefix);
+ NestedNameSpecifier QNNS =
+ getFullyQualifiedNestedNameSpecifier(Ctx, NNS, WithGlobalNsPrefix);
if (QNNS != NNS) {
Changed = true;
NNS = QNNS;
} else {
- NNS = nullptr;
+ NNS = std::nullopt;
}
} else {
NNS = createNestedNameSpecifierForScopeOf(
@@ -116,76 +117,81 @@ static bool getFullyQualifiedTemplateArgument(const ASTContext &Ctx,
}
static const Type *getFullyQualifiedTemplateType(const ASTContext &Ctx,
- const Type *TypePtr,
+ const TagType *TSTRecord,
+ ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifier Qualifier,
bool WithGlobalNsPrefix) {
- // DependentTemplateTypes exist within template declarations and
- // definitions. Therefore we shouldn't encounter them at the end of
- // a translation unit. If we do, the caller has made an error.
- assert(!isa<DependentTemplateSpecializationType>(TypePtr));
- // In case of template specializations, iterate over the arguments
- // and fully qualify them as well.
- if (const auto *TST = dyn_cast<const TemplateSpecializationType>(TypePtr)) {
- bool MightHaveChanged = false;
- SmallVector<TemplateArgument, 4> FQArgs;
- // Cheap to copy and potentially modified by
- // getFullyQualifedTemplateArgument.
- for (TemplateArgument Arg : TST->template_arguments()) {
- MightHaveChanged |= getFullyQualifiedTemplateArgument(
- Ctx, Arg, WithGlobalNsPrefix);
- FQArgs.push_back(Arg);
- }
+ // We are asked to fully qualify and we have a Record Type,
+ // which can point to a template instantiation with no sugar in any of
+ // its template argument, however we still need to fully qualify them.
+
+ const auto *TD = TSTRecord->getOriginalDecl();
+ const auto *TSTDecl = dyn_cast<ClassTemplateSpecializationDecl>(TD);
+ if (!TSTDecl)
+ return Ctx.getTagType(Keyword, Qualifier, TD, /*OwnsTag=*/false)
+ .getTypePtr();
+
+ const TemplateArgumentList &TemplateArgs = TSTDecl->getTemplateArgs();
+
+ bool MightHaveChanged = false;
+ SmallVector<TemplateArgument, 4> FQArgs;
+ for (unsigned int I = 0, E = TemplateArgs.size(); I != E; ++I) {
+ // cheap to copy and potentially modified by
+ // getFullyQualifedTemplateArgument
+ TemplateArgument Arg(TemplateArgs[I]);
+ MightHaveChanged |=
+ getFullyQualifiedTemplateArgument(Ctx, Arg, WithGlobalNsPrefix);
+ FQArgs.push_back(Arg);
+ }
- // If a fully qualified arg is different from the unqualified arg,
- // allocate new type in the AST.
- if (MightHaveChanged) {
- QualType QT = Ctx.getTemplateSpecializationType(
- TST->getTemplateName(), FQArgs,
- /*CanonicalArgs=*/{}, TST->desugar());
- // getTemplateSpecializationType returns a fully qualified
- // version of the specialization itself, so no need to qualify
- // it.
- return QT.getTypePtr();
- }
- } else if (const auto *TSTRecord = dyn_cast<const RecordType>(TypePtr)) {
- // We are asked to fully qualify and we have a Record Type,
- // which can point to a template instantiation with no sugar in any of
- // its template argument, however we still need to fully qualify them.
-
- if (const auto *TSTDecl =
- dyn_cast<ClassTemplateSpecializationDecl>(TSTRecord->getDecl())) {
- const TemplateArgumentList &TemplateArgs = TSTDecl->getTemplateArgs();
-
- bool MightHaveChanged = false;
- SmallVector<TemplateArgument, 4> FQArgs;
- for (unsigned int I = 0, E = TemplateArgs.size(); I != E; ++I) {
- // cheap to copy and potentially modified by
- // getFullyQualifedTemplateArgument
- TemplateArgument Arg(TemplateArgs[I]);
- MightHaveChanged |= getFullyQualifiedTemplateArgument(
- Ctx, Arg, WithGlobalNsPrefix);
- FQArgs.push_back(Arg);
- }
+ if (!MightHaveChanged)
+ return Ctx.getTagType(Keyword, Qualifier, TD, /*OwnsTag=*/false)
+ .getTypePtr();
+ // If a fully qualified arg is different from the unqualified arg,
+ // allocate new type in the AST.
+ TemplateName TN = Ctx.getQualifiedTemplateName(
+ Qualifier, /*TemplateKeyword=*/false,
+ TemplateName(TSTDecl->getSpecializedTemplate()));
+ QualType QT = Ctx.getTemplateSpecializationType(
+ Keyword, TN, FQArgs,
+ /*CanonicalArgs=*/{}, TSTRecord->getCanonicalTypeInternal());
+ // getTemplateSpecializationType returns a fully qualified
+ // version of the specialization itself, so no need to qualify
+ // it.
+ return QT.getTypePtr();
+}
- // If a fully qualified arg is different from the unqualified arg,
- // allocate new type in the AST.
- if (MightHaveChanged) {
- TemplateName TN(TSTDecl->getSpecializedTemplate());
- QualType QT = Ctx.getTemplateSpecializationType(
- TN, FQArgs,
- /*CanonicalArgs=*/{}, TSTRecord->getCanonicalTypeInternal());
- // getTemplateSpecializationType returns a fully qualified
- // version of the specialization itself, so no need to qualify
- // it.
- return QT.getTypePtr();
- }
- }
+static const Type *
+getFullyQualifiedTemplateType(const ASTContext &Ctx,
+ const TemplateSpecializationType *TST,
+ bool WithGlobalNsPrefix) {
+ TemplateName TName = TST->getTemplateName();
+ bool MightHaveChanged =
+ getFullyQualifiedTemplateName(Ctx, TName, WithGlobalNsPrefix);
+ SmallVector<TemplateArgument, 4> FQArgs;
+ // Cheap to copy and potentially modified by
+ // getFullyQualifedTemplateArgument.
+ for (TemplateArgument Arg : TST->template_arguments()) {
+ MightHaveChanged |=
+ getFullyQualifiedTemplateArgument(Ctx, Arg, WithGlobalNsPrefix);
+ FQArgs.push_back(Arg);
}
- return TypePtr;
+
+ if (!MightHaveChanged)
+ return TST;
+
+ QualType NewQT =
+ Ctx.getTemplateSpecializationType(TST->getKeyword(), TName, FQArgs,
+ /*CanonicalArgs=*/{}, TST->desugar());
+ // getTemplateSpecializationType returns a fully qualified
+ // version of the specialization itself, so no need to qualify
+ // it.
+ return NewQT.getTypePtr();
}
-static NestedNameSpecifier *createOuterNNS(const ASTContext &Ctx, const Decl *D,
- bool FullyQualify,
- bool WithGlobalNsPrefix) {
+static NestedNameSpecifier createOuterNNS(const ASTContext &Ctx, const Decl *D,
+ bool FullyQualify,
+ bool WithGlobalNsPrefix) {
const DeclContext *DC = D->getDeclContext();
if (const auto *NS = dyn_cast<NamespaceDecl>(DC)) {
while (NS && NS->isInline()) {
@@ -195,71 +201,63 @@ static NestedNameSpecifier *createOuterNNS(const ASTContext &Ctx, const Decl *D,
if (NS && NS->getDeclName()) {
return createNestedNameSpecifier(Ctx, NS, WithGlobalNsPrefix);
}
- return nullptr; // no starting '::', no anonymous
- } else if (const auto *TD = dyn_cast<TagDecl>(DC)) {
- return createNestedNameSpecifier(Ctx, TD, FullyQualify, WithGlobalNsPrefix);
- } else if (const auto *TDD = dyn_cast<TypedefNameDecl>(DC)) {
- return createNestedNameSpecifier(
- Ctx, TDD, FullyQualify, WithGlobalNsPrefix);
- } else if (WithGlobalNsPrefix && DC->isTranslationUnit()) {
- return NestedNameSpecifier::GlobalSpecifier(Ctx);
+ return std::nullopt; // no starting '::', no anonymous
}
- return nullptr; // no starting '::' if |WithGlobalNsPrefix| is false
+ if (const auto *TD = dyn_cast<TagDecl>(DC))
+ return createNestedNameSpecifier(Ctx, TD, FullyQualify, WithGlobalNsPrefix);
+ if (const auto *TDD = dyn_cast<TypedefNameDecl>(DC))
+ return createNestedNameSpecifier(Ctx, TDD, FullyQualify,
+ WithGlobalNsPrefix);
+ if (WithGlobalNsPrefix && DC->isTranslationUnit())
+ return NestedNameSpecifier::getGlobal();
+ return std::nullopt; // no starting '::' if |WithGlobalNsPrefix| is false
}
/// Return a fully qualified version of this name specifier.
-static NestedNameSpecifier *getFullyQualifiedNestedNameSpecifier(
- const ASTContext &Ctx, NestedNameSpecifier *Scope,
- bool WithGlobalNsPrefix) {
- switch (Scope->getKind()) {
- case NestedNameSpecifier::Global:
- case NestedNameSpecifier::Super:
- // Already fully qualified
- return Scope;
- case NestedNameSpecifier::Namespace:
- return TypeName::createNestedNameSpecifier(
- Ctx, Scope->getAsNamespace()->getNamespace(), WithGlobalNsPrefix);
- case NestedNameSpecifier::Identifier:
- // A function or some other construct that makes it un-namable
- // at the end of the TU. Skip the current component of the name,
- // but use the name of it's prefix.
- return getFullyQualifiedNestedNameSpecifier(
- Ctx, Scope->getPrefix(), WithGlobalNsPrefix);
- case NestedNameSpecifier::TypeSpec: {
- const Type *Type = Scope->getAsType();
- // Find decl context.
- const TagDecl *TD = nullptr;
- if (const TagType *TagDeclType = Type->getAs<TagType>()) {
- TD = TagDeclType->getDecl();
- } else {
- TD = Type->getAsCXXRecordDecl();
- }
- if (TD) {
- return TypeName::createNestedNameSpecifier(Ctx, TD,
- true /*FullyQualified*/,
- WithGlobalNsPrefix);
- } else if (const auto *TDD = dyn_cast<TypedefType>(Type)) {
- return TypeName::createNestedNameSpecifier(Ctx, TDD->getDecl(),
- true /*FullyQualified*/,
- WithGlobalNsPrefix);
- }
+static NestedNameSpecifier getFullyQualifiedNestedNameSpecifier(
+ const ASTContext &Ctx, NestedNameSpecifier Scope, bool WithGlobalNsPrefix) {
+ switch (Scope.getKind()) {
+ case NestedNameSpecifier::Kind::Null:
+ llvm_unreachable("can't fully qualify the empty nested name specifier");
+ case NestedNameSpecifier::Kind::Global:
+ case NestedNameSpecifier::Kind::MicrosoftSuper:
+ // Already fully qualified
+ return Scope;
+ case NestedNameSpecifier::Kind::Namespace:
+ return TypeName::createNestedNameSpecifier(
+ Ctx, Scope.getAsNamespaceAndPrefix().Namespace->getNamespace(),
+ WithGlobalNsPrefix);
+ case NestedNameSpecifier::Kind::Type: {
+ const Type *Type = Scope.getAsType();
+ // Find decl context.
+ const TypeDecl *TD;
+ if (const TagType *TagDeclType = Type->getAs<TagType>())
+ TD = TagDeclType->getOriginalDecl();
+ else if (const auto *D = dyn_cast<TypedefType>(Type))
+ TD = D->getDecl();
+ else
return Scope;
- }
+ return TypeName::createNestedNameSpecifier(Ctx, TD, /*FullyQualify=*/true,
+ WithGlobalNsPrefix);
+ }
}
llvm_unreachable("bad NNS kind");
}
/// Create a nested name specifier for the declaring context of
/// the type.
-static NestedNameSpecifier *createNestedNameSpecifierForScopeOf(
- const ASTContext &Ctx, const Decl *Decl,
- bool FullyQualified, bool WithGlobalNsPrefix) {
+static NestedNameSpecifier
+createNestedNameSpecifierForScopeOf(const ASTContext &Ctx, const Decl *Decl,
+ bool FullyQualified,
+ bool WithGlobalNsPrefix) {
assert(Decl);
const DeclContext *DC = Decl->getDeclContext()->getRedeclContext();
const auto *Outer = dyn_cast<NamedDecl>(DC);
const auto *OuterNS = dyn_cast<NamespaceDecl>(DC);
- if (Outer && !(OuterNS && OuterNS->isAnonymousNamespace())) {
+ if (OuterNS && OuterNS->isAnonymousNamespace())
+ OuterNS = dyn_cast<NamespaceDecl>(OuterNS->getParent());
+ if (Outer) {
if (const auto *CxxDecl = dyn_cast<CXXRecordDecl>(DC)) {
if (ClassTemplateDecl *ClassTempl =
CxxDecl->getDescribedClassTemplate()) {
@@ -288,76 +286,80 @@ static NestedNameSpecifier *createNestedNameSpecifierForScopeOf(
Ctx, TD, FullyQualified, WithGlobalNsPrefix);
} else if (isa<TranslationUnitDecl>(Outer)) {
// Context is the TU. Nothing needs to be done.
- return nullptr;
+ return std::nullopt;
} else {
// Decl's context was neither the TU, a namespace, nor a
// TagDecl, which means it is a type local to a scope, and not
// accessible at the end of the TU.
- return nullptr;
+ return std::nullopt;
}
} else if (WithGlobalNsPrefix && DC->isTranslationUnit()) {
- return NestedNameSpecifier::GlobalSpecifier(Ctx);
+ return NestedNameSpecifier::getGlobal();
}
- return nullptr;
+ return std::nullopt;
}
/// Create a nested name specifier for the declaring context of
/// the type.
-static NestedNameSpecifier *createNestedNameSpecifierForScopeOf(
- const ASTContext &Ctx, const Type *TypePtr,
- bool FullyQualified, bool WithGlobalNsPrefix) {
- if (!TypePtr) return nullptr;
+static NestedNameSpecifier
+createNestedNameSpecifierForScopeOf(const ASTContext &Ctx, const Type *TypePtr,
+ bool FullyQualified,
+ bool WithGlobalNsPrefix) {
+ if (!TypePtr)
+ return std::nullopt;
Decl *Decl = nullptr;
// There are probably other cases ...
if (const auto *TDT = dyn_cast<TypedefType>(TypePtr)) {
Decl = TDT->getDecl();
} else if (const auto *TagDeclType = dyn_cast<TagType>(TypePtr)) {
- Decl = TagDeclType->getDecl();
+ Decl = TagDeclType->getOriginalDecl();
} else if (const auto *TST = dyn_cast<TemplateSpecializationType>(TypePtr)) {
Decl = TST->getTemplateName().getAsTemplateDecl();
} else {
Decl = TypePtr->getAsCXXRecordDecl();
}
- if (!Decl) return nullptr;
+ if (!Decl)
+ return std::nullopt;
return createNestedNameSpecifierForScopeOf(
Ctx, Decl, FullyQualified, WithGlobalNsPrefix);
}
-NestedNameSpecifier *createNestedNameSpecifier(const ASTContext &Ctx,
- const NamespaceDecl *Namespace,
- bool WithGlobalNsPrefix) {
+static NestedNameSpecifier
+createNestedNameSpecifier(const ASTContext &Ctx, const NamespaceDecl *Namespace,
+ bool WithGlobalNsPrefix) {
while (Namespace && Namespace->isInline()) {
// Ignore inline namespace;
Namespace = dyn_cast<NamespaceDecl>(Namespace->getDeclContext());
}
- if (!Namespace) return nullptr;
+ if (!Namespace)
+ return std::nullopt;
- bool FullyQualified = true; // doesn't matter, DeclContexts are namespaces
- return NestedNameSpecifier::Create(
- Ctx,
- createOuterNNS(Ctx, Namespace, FullyQualified, WithGlobalNsPrefix),
- Namespace);
+ bool FullyQualify = true; // doesn't matter, DeclContexts are namespaces
+ return NestedNameSpecifier(
+ Ctx, Namespace,
+ createOuterNNS(Ctx, Namespace, FullyQualify, WithGlobalNsPrefix));
}
-NestedNameSpecifier *createNestedNameSpecifier(const ASTContext &Ctx,
- const TypeDecl *TD,
- bool FullyQualify,
- bool WithGlobalNsPrefix) {
- const Type *TypePtr = TD->getTypeForDecl();
- if (isa<const TemplateSpecializationType>(TypePtr) ||
- isa<const RecordType>(TypePtr)) {
+NestedNameSpecifier createNestedNameSpecifier(const ASTContext &Ctx,
+ const TypeDecl *TD,
+ bool FullyQualify,
+ bool WithGlobalNsPrefix) {
+ const Type *TypePtr = Ctx.getTypeDeclType(TD).getTypePtr();
+ if (auto *RD = dyn_cast<TagType>(TypePtr)) {
// We are asked to fully qualify and we have a Record Type (which
// may point to a template specialization) or Template
// Specialization Type. We need to fully qualify their arguments.
-
- TypePtr = getFullyQualifiedTemplateType(Ctx, TypePtr, WithGlobalNsPrefix);
+ TypePtr = getFullyQualifiedTemplateType(
+ Ctx, RD, ElaboratedTypeKeyword::None,
+ createOuterNNS(Ctx, TD, FullyQualify, WithGlobalNsPrefix),
+ WithGlobalNsPrefix);
+ } else if (auto *TST = dyn_cast<TemplateSpecializationType>(TypePtr)) {
+ TypePtr = getFullyQualifiedTemplateType(Ctx, TST, WithGlobalNsPrefix);
}
-
- return NestedNameSpecifier::Create(
- Ctx, createOuterNNS(Ctx, TD, FullyQualify, WithGlobalNsPrefix), TypePtr);
+ return NestedNameSpecifier(TypePtr);
}
/// Return the fully qualified type, including fully-qualified
@@ -381,7 +383,7 @@ QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx,
Qualifiers Quals = QT.getQualifiers();
// Fully qualify the pointee and class types.
QT = getFullyQualifiedType(QT->getPointeeType(), Ctx, WithGlobalNsPrefix);
- NestedNameSpecifier *Qualifier = getFullyQualifiedNestedNameSpecifier(
+ NestedNameSpecifier Qualifier = getFullyQualifiedNestedNameSpecifier(
Ctx, MPT->getQualifier(), WithGlobalNsPrefix);
QT = Ctx.getMemberPointerType(QT, Qualifier,
MPT->getMostRecentCXXRecordDecl());
@@ -434,45 +436,48 @@ QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx,
QT = Ctx.getQualifiedType(QT, Quals);
}
- NestedNameSpecifier *Prefix = nullptr;
+ if (const auto *TST =
+ dyn_cast<const TemplateSpecializationType>(QT.getTypePtr())) {
+
+ const Type *T = getFullyQualifiedTemplateType(Ctx, TST, WithGlobalNsPrefix);
+ if (T == TST)
+ return QT;
+ return Ctx.getQualifiedType(T, QT.getQualifiers());
+ }
+
// Local qualifiers are attached to the QualType outside of the
// elaborated type. Retrieve them before descending into the
// elaborated type.
Qualifiers PrefixQualifiers = QT.getLocalQualifiers();
QT = QualType(QT.getTypePtr(), 0);
- ElaboratedTypeKeyword Keyword = ElaboratedTypeKeyword::None;
- if (const auto *ETypeInput = dyn_cast<ElaboratedType>(QT.getTypePtr())) {
- QT = ETypeInput->getNamedType();
- assert(!QT.hasLocalQualifiers());
- Keyword = ETypeInput->getKeyword();
- }
// We don't consider the alias introduced by `using a::X` as a new type.
// The qualified name is still a::X.
if (const auto *UT = QT->getAs<UsingType>()) {
- QT = Ctx.getQualifiedType(UT->getUnderlyingType(), PrefixQualifiers);
+ QT = Ctx.getQualifiedType(UT->desugar(), PrefixQualifiers);
return getFullyQualifiedType(QT, Ctx, WithGlobalNsPrefix);
}
// Create a nested name specifier if needed.
- Prefix = createNestedNameSpecifierForScopeOf(Ctx, QT.getTypePtr(),
- true /*FullyQualified*/,
- WithGlobalNsPrefix);
+ NestedNameSpecifier Prefix = createNestedNameSpecifierForScopeOf(
+ Ctx, QT.getTypePtr(), true /*FullyQualified*/, WithGlobalNsPrefix);
// In case of template specializations iterate over the arguments and
// fully qualify them as well.
- if (isa<const TemplateSpecializationType>(QT.getTypePtr()) ||
- isa<const RecordType>(QT.getTypePtr())) {
+ if (const auto *TT = dyn_cast<TagType>(QT.getTypePtr())) {
// We are asked to fully qualify and we have a Record Type (which
// may point to a template specialization) or Template
// Specialization Type. We need to fully qualify their arguments.
const Type *TypePtr = getFullyQualifiedTemplateType(
- Ctx, QT.getTypePtr(), WithGlobalNsPrefix);
+ Ctx, TT, TT->getKeyword(), Prefix, WithGlobalNsPrefix);
QT = QualType(TypePtr, 0);
- }
- if (Prefix || Keyword != ElaboratedTypeKeyword::None) {
- QT = Ctx.getElaboratedType(Keyword, Prefix, QT);
+ } else if (const auto *TT = dyn_cast<TypedefType>(QT.getTypePtr())) {
+ QT = Ctx.getTypedefType(
+ TT->getKeyword(), Prefix, TT->getDecl(),
+ getFullyQualifiedType(TT->desugar(), Ctx, WithGlobalNsPrefix));
+ } else {
+ assert(!Prefix && "Unhandled type node");
}
QT = Ctx.getQualifiedType(QT, PrefixQualifiers);
return QT;
@@ -486,5 +491,12 @@ std::string getFullyQualifiedName(QualType QT,
return FQQT.getAsString(Policy);
}
+NestedNameSpecifier getFullyQualifiedDeclaredContext(const ASTContext &Ctx,
+ const Decl *Decl,
+ bool WithGlobalNsPrefix) {
+ return createNestedNameSpecifierForScopeOf(Ctx, Decl, /*FullyQualified=*/true,
+ WithGlobalNsPrefix);
+}
+
} // end namespace TypeName
} // end namespace clang
diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp
index 760b2fc..f1f21f4 100644
--- a/clang/lib/AST/RecordLayoutBuilder.cpp
+++ b/clang/lib/AST/RecordLayoutBuilder.cpp
@@ -2012,8 +2012,7 @@ void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D,
} else if (const BuiltinType *BTy = BaseTy->getAs<BuiltinType>()) {
performBuiltinTypeAlignmentUpgrade(BTy);
} else if (const RecordType *RT = BaseTy->getAs<RecordType>()) {
- const RecordDecl *RD = RT->getDecl();
- assert(RD && "Expected non-null RecordDecl.");
+ const RecordDecl *RD = RT->getOriginalDecl();
const ASTRecordLayout &FieldRecord = Context.getASTRecordLayout(RD);
PreferredAlign = FieldRecord.getPreferredAlignment();
}
@@ -2128,7 +2127,8 @@ void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D,
// TODO: Takes no account the alignment of the outer struct
if (FieldOffset % OriginalFieldAlign != 0)
Diag(D->getLocation(), diag::warn_unaligned_access)
- << Context.getTypeDeclType(RD) << D->getName() << D->getType();
+ << Context.getCanonicalTagType(RD) << D->getName()
+ << D->getType();
}
}
@@ -2193,8 +2193,7 @@ void ItaniumRecordLayoutBuilder::FinishLayout(const NamedDecl *D) {
InBits = false;
}
Diag(RD->getLocation(), diag::warn_padded_struct_size)
- << Context.getTypeDeclType(RD)
- << PadSize
+ << Context.getCanonicalTagType(RD) << PadSize
<< (InBits ? 1 : 0); // (byte|bit)
}
@@ -2212,7 +2211,7 @@ void ItaniumRecordLayoutBuilder::FinishLayout(const NamedDecl *D) {
Context.getLangOpts().getClangABICompat() <=
LangOptions::ClangABI::Ver15))
Diag(D->getLocation(), diag::warn_unnecessary_packed)
- << Context.getTypeDeclType(RD);
+ << Context.getCanonicalTagType(RD);
}
}
@@ -2306,7 +2305,7 @@ static void CheckFieldPadding(const ASTContext &Context, bool IsUnion,
Context.getDiagnostics().Report(D->getLocation(),
Diagnostic)
<< getPaddingDiagFromTagKind(D->getParent()->getTagKind())
- << Context.getTypeDeclType(D->getParent()) << PadSize
+ << Context.getCanonicalTagType(D->getParent()) << PadSize
<< (InBits ? 1 : 0) // (byte|bit)
<< D->getIdentifier();
} else {
@@ -2315,7 +2314,7 @@ static void CheckFieldPadding(const ASTContext &Context, bool IsUnion,
Context.getDiagnostics().Report(D->getLocation(),
Diagnostic)
<< getPaddingDiagFromTagKind(D->getParent()->getTagKind())
- << Context.getTypeDeclType(D->getParent()) << PadSize
+ << Context.getCanonicalTagType(D->getParent()) << PadSize
<< (InBits ? 1 : 0); // (byte|bit)
}
}
@@ -2714,7 +2713,7 @@ MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
else {
if (auto RT =
FD->getType()->getBaseElementTypeUnsafe()->getAs<RecordType>()) {
- auto const &Layout = Context.getASTRecordLayout(RT->getDecl());
+ auto const &Layout = Context.getASTRecordLayout(RT->getOriginalDecl());
EndsWithZeroSizedObject = Layout.endsWithZeroSizedObject();
FieldRequiredAlignment = std::max(FieldRequiredAlignment,
Layout.getRequiredAlignment());
@@ -3273,7 +3272,7 @@ void MicrosoftRecordLayoutBuilder::finalizeLayout(const RecordDecl *RD) {
Context.getDiagnostics().Report(RD->getLocation(),
diag::warn_padded_struct_size)
- << Context.getTypeDeclType(RD) << PadSize
+ << Context.getCanonicalTagType(RD) << PadSize
<< (InBits ? 1 : 0); // (byte|bit)
}
}
@@ -3631,7 +3630,7 @@ static void DumpRecordLayout(raw_ostream &OS, const RecordDecl *RD,
auto CXXRD = dyn_cast<CXXRecordDecl>(RD);
PrintOffset(OS, Offset, IndentLevel);
- OS << C.getTypeDeclType(const_cast<RecordDecl *>(RD));
+ OS << C.getCanonicalTagType(const_cast<RecordDecl *>(RD));
if (Description)
OS << ' ' << Description;
if (CXXRD && CXXRD->isEmpty())
@@ -3697,8 +3696,8 @@ static void DumpRecordLayout(raw_ostream &OS, const RecordDecl *RD,
// Recursively dump fields of record type.
if (auto RT = Field->getType()->getAs<RecordType>()) {
- DumpRecordLayout(OS, RT->getDecl(), C, FieldOffset, IndentLevel,
- Field->getName().data(),
+ DumpRecordLayout(OS, RT->getOriginalDecl()->getDefinitionOrSelf(), C,
+ FieldOffset, IndentLevel, Field->getName().data(),
/*PrintSizeInfo=*/false,
/*IncludeVirtualBases=*/true);
continue;
@@ -3781,7 +3780,7 @@ void ASTContext::DumpRecordLayout(const RecordDecl *RD, raw_ostream &OS,
// in libFrontend.
const ASTRecordLayout &Info = getASTRecordLayout(RD);
- OS << "Type: " << getTypeDeclType(RD) << "\n";
+ OS << "Type: " << getCanonicalTagType(RD) << "\n";
OS << "\nLayout: ";
OS << "<ASTRecordLayout\n";
OS << " Size:" << toBits(Info.getSize()) << "\n";
diff --git a/clang/lib/AST/ScanfFormatString.cpp b/clang/lib/AST/ScanfFormatString.cpp
index 1227edd..31c001d 100644
--- a/clang/lib/AST/ScanfFormatString.cpp
+++ b/clang/lib/AST/ScanfFormatString.cpp
@@ -432,9 +432,10 @@ bool ScanfSpecifier::fixType(QualType QT, QualType RawQT,
// If it's an enum, get its underlying type.
if (const EnumType *ETy = PT->getAs<EnumType>()) {
// Don't try to fix incomplete enums.
- if (!ETy->getDecl()->isComplete())
+ const EnumDecl *ED = ETy->getOriginalDecl()->getDefinitionOrSelf();
+ if (!ED->isComplete())
return false;
- PT = ETy->getDecl()->getIntegerType();
+ PT = ED->getIntegerType();
}
const BuiltinType *BT = PT->getAs<BuiltinType>();
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index 6ba5ec8..afccba8 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -454,10 +454,7 @@ void StmtPrinter::VisitMSDependentExistsStmt(MSDependentExistsStmt *Node) {
else
OS << "__if_not_exists (";
- if (NestedNameSpecifier *Qualifier
- = Node->getQualifierLoc().getNestedNameSpecifier())
- Qualifier->print(OS, Policy);
-
+ Node->getQualifierLoc().getNestedNameSpecifier().print(OS, Policy);
OS << Node->getNameInfo() << ") ";
PrintRawCompoundStmt(Node->getSubStmt());
@@ -1309,8 +1306,7 @@ void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) {
TPOD->printAsExpr(OS, Policy);
return;
}
- if (NestedNameSpecifier *Qualifier = Node->getQualifier())
- Qualifier->print(OS, Policy);
+ Node->getQualifier().print(OS, Policy);
if (Node->hasTemplateKeyword())
OS << "template ";
@@ -1359,8 +1355,7 @@ void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) {
void StmtPrinter::VisitDependentScopeDeclRefExpr(
DependentScopeDeclRefExpr *Node) {
- if (NestedNameSpecifier *Qualifier = Node->getQualifier())
- Qualifier->print(OS, Policy);
+ Node->getQualifier().print(OS, Policy);
if (Node->hasTemplateKeyword())
OS << "template ";
OS << Node->getNameInfo();
@@ -1369,8 +1364,7 @@ void StmtPrinter::VisitDependentScopeDeclRefExpr(
}
void StmtPrinter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *Node) {
- if (Node->getQualifier())
- Node->getQualifier()->print(OS, Policy);
+ Node->getQualifier().print(OS, Policy);
if (Node->hasTemplateKeyword())
OS << "template ";
OS << Node->getNameInfo();
@@ -1778,8 +1772,7 @@ void StmtPrinter::VisitMemberExpr(MemberExpr *Node) {
if (FD->isAnonymousStructOrUnion())
return;
- if (NestedNameSpecifier *Qualifier = Node->getQualifier())
- Qualifier->print(OS, Policy);
+ Node->getQualifier().print(OS, Policy);
if (Node->hasTemplateKeyword())
OS << "template ";
OS << Node->getMemberNameInfo();
@@ -2177,9 +2170,7 @@ void StmtPrinter::VisitMSPropertyRefExpr(MSPropertyRefExpr *Node) {
OS << "->";
else
OS << ".";
- if (NestedNameSpecifier *Qualifier =
- Node->getQualifierLoc().getNestedNameSpecifier())
- Qualifier->print(OS, Policy);
+ Node->getQualifierLoc().getNestedNameSpecifier().print(OS, Policy);
OS << Node->getPropertyDecl()->getDeclName();
}
@@ -2509,8 +2500,7 @@ void StmtPrinter::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
OS << "->";
else
OS << '.';
- if (E->getQualifier())
- E->getQualifier()->print(OS, Policy);
+ E->getQualifier().print(OS, Policy);
OS << "~";
if (const IdentifierInfo *II = E->getDestroyedTypeIdentifier())
@@ -2572,8 +2562,7 @@ void StmtPrinter::VisitCXXDependentScopeMemberExpr(
PrintExpr(Node->getBase());
OS << (Node->isArrow() ? "->" : ".");
}
- if (NestedNameSpecifier *Qualifier = Node->getQualifier())
- Qualifier->print(OS, Policy);
+ Node->getQualifier().print(OS, Policy);
if (Node->hasTemplateKeyword())
OS << "template ";
OS << Node->getMemberNameInfo();
@@ -2586,8 +2575,7 @@ void StmtPrinter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *Node) {
PrintExpr(Node->getBase());
OS << (Node->isArrow() ? "->" : ".");
}
- if (NestedNameSpecifier *Qualifier = Node->getQualifier())
- Qualifier->print(OS, Policy);
+ Node->getQualifier().print(OS, Policy);
if (Node->hasTemplateKeyword())
OS << "template ";
OS << Node->getMemberNameInfo();
@@ -2678,8 +2666,7 @@ void StmtPrinter::VisitCXXParenListInitExpr(CXXParenListInitExpr *Node) {
void StmtPrinter::VisitConceptSpecializationExpr(ConceptSpecializationExpr *E) {
NestedNameSpecifierLoc NNS = E->getNestedNameSpecifierLoc();
- if (NNS)
- NNS.getNestedNameSpecifier()->print(OS, Policy);
+ NNS.getNestedNameSpecifier().print(OS, Policy);
if (E->getTemplateKWLoc().isValid())
OS << "template ";
OS << E->getFoundDecl()->getName();
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index 4c36f24..5fee884 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -65,7 +65,7 @@ namespace {
/// Visit a nested-name-specifier that occurs within an expression
/// or statement.
- virtual void VisitNestedNameSpecifier(NestedNameSpecifier *NNS) = 0;
+ virtual void VisitNestedNameSpecifier(NestedNameSpecifier NNS) = 0;
/// Visit a template name that occurs within an expression or
/// statement.
@@ -167,10 +167,10 @@ namespace {
ID.AddPointer(II);
}
- void VisitNestedNameSpecifier(NestedNameSpecifier *NNS) override {
+ void VisitNestedNameSpecifier(NestedNameSpecifier NNS) override {
if (Canonical)
- NNS = Context.getCanonicalNestedNameSpecifier(NNS);
- ID.AddPointer(NNS);
+ NNS = NNS.getCanonical();
+ NNS.Profile(ID);
}
void VisitTemplateName(TemplateName Name) override {
@@ -226,11 +226,10 @@ namespace {
void VisitTemplateName(TemplateName Name) override {
Hash.AddTemplateName(Name);
}
- void VisitNestedNameSpecifier(NestedNameSpecifier *NNS) override {
- ID.AddBoolean(NNS);
- if (NNS) {
+ void VisitNestedNameSpecifier(NestedNameSpecifier NNS) override {
+ ID.AddBoolean(bool(NNS));
+ if (NNS)
Hash.AddNestedNameSpecifier(NNS);
- }
}
};
}
@@ -2645,8 +2644,10 @@ void OpenACCClauseProfiler::VisitFirstPrivateClause(
const OpenACCFirstPrivateClause &Clause) {
VisitClauseWithVarList(Clause);
- for (auto *VD : Clause.getInitRecipes())
- Profiler.VisitDecl(VD);
+ for (auto &Recipe : Clause.getInitRecipes()) {
+ Profiler.VisitDecl(Recipe.RecipeDecl);
+ Profiler.VisitDecl(Recipe.InitFromTemporary);
+ }
}
void OpenACCClauseProfiler::VisitAttachClause(
diff --git a/clang/lib/AST/TemplateBase.cpp b/clang/lib/AST/TemplateBase.cpp
index 7a0f740..76050ce 100644
--- a/clang/lib/AST/TemplateBase.cpp
+++ b/clang/lib/AST/TemplateBase.cpp
@@ -57,7 +57,7 @@ static void printIntegral(const TemplateArgument &TemplArg, raw_ostream &Out,
if (Policy.UseEnumerators) {
if (const EnumType *ET = T->getAs<EnumType>()) {
- for (const EnumConstantDecl *ECD : ET->getDecl()->enumerators()) {
+ for (const EnumConstantDecl *ECD : ET->getOriginalDecl()->enumerators()) {
// In Sema::CheckTemplateArugment, enum template arguments value are
// extended to the size of the integer underlying the enum type. This
// may create a size difference between the enum value and template
@@ -596,6 +596,29 @@ void TemplateArgument::print(const PrintingPolicy &Policy, raw_ostream &Out,
// TemplateArgumentLoc Implementation
//===----------------------------------------------------------------------===//
+TemplateArgumentLoc::TemplateArgumentLoc(ASTContext &Ctx,
+ const TemplateArgument &Argument,
+ SourceLocation TemplateKWLoc,
+ NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateNameLoc,
+ SourceLocation EllipsisLoc)
+ : Argument(Argument),
+ LocInfo(Ctx, TemplateKWLoc, QualifierLoc, TemplateNameLoc, EllipsisLoc) {
+ assert(Argument.getKind() == TemplateArgument::Template ||
+ Argument.getKind() == TemplateArgument::TemplateExpansion);
+ assert(QualifierLoc.getNestedNameSpecifier() ==
+ Argument.getAsTemplateOrTemplatePattern().getQualifier());
+}
+
+NestedNameSpecifierLoc TemplateArgumentLoc::getTemplateQualifierLoc() const {
+ if (Argument.getKind() != TemplateArgument::Template &&
+ Argument.getKind() != TemplateArgument::TemplateExpansion)
+ return NestedNameSpecifierLoc();
+ return NestedNameSpecifierLoc(
+ Argument.getAsTemplateOrTemplatePattern().getQualifier(),
+ LocInfo.getTemplate()->QualifierLocData);
+}
+
SourceRange TemplateArgumentLoc::getSourceRange() const {
switch (Argument.getKind()) {
case TemplateArgument::Expression:
@@ -702,10 +725,11 @@ const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB,
}
clang::TemplateArgumentLocInfo::TemplateArgumentLocInfo(
- ASTContext &Ctx, NestedNameSpecifierLoc QualifierLoc,
- SourceLocation TemplateNameLoc, SourceLocation EllipsisLoc) {
+ ASTContext &Ctx, SourceLocation TemplateKWLoc,
+ NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateNameLoc,
+ SourceLocation EllipsisLoc) {
TemplateTemplateArgLocInfo *Template = new (Ctx) TemplateTemplateArgLocInfo;
- Template->Qualifier = QualifierLoc.getNestedNameSpecifier();
+ Template->TemplateKwLoc = TemplateKWLoc;
Template->QualifierLocData = QualifierLoc.getOpaqueData();
Template->TemplateNameLoc = TemplateNameLoc;
Template->EllipsisLoc = EllipsisLoc;
diff --git a/clang/lib/AST/TemplateName.cpp b/clang/lib/AST/TemplateName.cpp
index 5b7abc4..c171516 100644
--- a/clang/lib/AST/TemplateName.cpp
+++ b/clang/lib/AST/TemplateName.cpp
@@ -289,10 +289,30 @@ QualifiedTemplateName *TemplateName::getAsQualifiedTemplateName() const {
return dyn_cast_if_present<QualifiedTemplateName *>(Storage);
}
+QualifiedTemplateName *
+TemplateName::getAsAdjustedQualifiedTemplateName() const {
+ for (std::optional<TemplateName> Cur = *this; Cur;
+ Cur = Cur->desugar(/*IgnoreDeduced=*/true))
+ if (QualifiedTemplateName *N = Cur->getAsQualifiedTemplateName())
+ return N;
+ return nullptr;
+}
+
DependentTemplateName *TemplateName::getAsDependentTemplateName() const {
return Storage.dyn_cast<DependentTemplateName *>();
}
+NestedNameSpecifier TemplateName::getQualifier() const {
+ for (std::optional<TemplateName> Cur = *this; Cur;
+ Cur = Cur->desugar(/*IgnoreDeduced=*/true)) {
+ if (DependentTemplateName *N = Cur->getAsDependentTemplateName())
+ return N->getQualifier();
+ if (QualifiedTemplateName *N = Cur->getAsQualifiedTemplateName())
+ return N->getQualifier();
+ }
+ return std::nullopt;
+}
+
UsingShadowDecl *TemplateName::getAsUsingShadowDecl() const {
if (Decl *D = Storage.dyn_cast<Decl *>())
if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D))
@@ -303,24 +323,21 @@ UsingShadowDecl *TemplateName::getAsUsingShadowDecl() const {
}
DependentTemplateStorage::DependentTemplateStorage(
- NestedNameSpecifier *Qualifier, IdentifierOrOverloadedOperator Name,
+ NestedNameSpecifier Qualifier, IdentifierOrOverloadedOperator Name,
bool HasTemplateKeyword)
: Qualifier(Qualifier, HasTemplateKeyword), Name(Name) {
- assert((!Qualifier || Qualifier->isDependent()) &&
+ assert((!Qualifier || Qualifier.isDependent()) &&
"Qualifier must be dependent");
}
TemplateNameDependence DependentTemplateStorage::getDependence() const {
- auto D = TemplateNameDependence::DependentInstantiation;
- if (NestedNameSpecifier *Qualifier = getQualifier())
- D |= toTemplateNameDependence(Qualifier->getDependence());
- return D;
+ return toTemplateNameDependence(getQualifier().getDependence()) |
+ TemplateNameDependence::DependentInstantiation;
}
void DependentTemplateStorage::print(raw_ostream &OS,
const PrintingPolicy &Policy) const {
- if (NestedNameSpecifier *NNS = getQualifier())
- NNS->print(OS, Policy);
+ getQualifier().print(OS, Policy);
if (hasTemplateKeyword())
OS << "template ";
@@ -363,16 +380,13 @@ TemplateNameDependence TemplateName::getDependence() const {
case NameKind::QualifiedTemplate: {
QualifiedTemplateName *S = getAsQualifiedTemplateName();
TemplateNameDependence D = S->getUnderlyingTemplate().getDependence();
- if (NestedNameSpecifier *NNS = S->getQualifier())
- D |= toTemplateNameDependence(NNS->getDependence());
+ D |= toTemplateNameDependence(S->getQualifier().getDependence());
return D;
}
case NameKind::DependentTemplate: {
DependentTemplateName *S = getAsDependentTemplateName();
- auto D = TemplateNameDependence::DependentInstantiation;
- if (NestedNameSpecifier *Qualifier = S->getQualifier())
- D |= toTemplateNameDependence(Qualifier->getDependence());
- return D;
+ return toTemplateNameDependence(S->getQualifier().getDependence()) |
+ TemplateNameDependence::DependentInstantiation;
}
case NameKind::SubstTemplateTemplateParm: {
auto *S = getAsSubstTemplateTemplateParm();
@@ -434,18 +448,20 @@ void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
Template = cast<TemplateDecl>(Template->getCanonicalDecl());
if (handleAnonymousTTP(Template, OS))
return;
- if (Qual == Qualified::None)
+ if (Qual == Qualified::None || Policy.SuppressScope) {
OS << *Template;
- else
- Template->printQualifiedName(OS, Policy);
+ } else {
+ PrintingPolicy NestedNamePolicy = Policy;
+ NestedNamePolicy.SuppressUnwrittenScope = true;
+ Template->printQualifiedName(OS, NestedNamePolicy);
+ }
} else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
if (Policy.PrintAsCanonical) {
QTN->getUnderlyingTemplate().print(OS, Policy, Qual);
return;
}
- if (NestedNameSpecifier *NNS = QTN->getQualifier();
- Qual != Qualified::None && NNS)
- NNS->print(OS, Policy);
+ if (Qual != Qualified::None)
+ QTN->getQualifier().print(OS, Policy);
if (QTN->hasTemplateKeyword())
OS << "template ";
diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp
index 6b524cf..0856160 100644
--- a/clang/lib/AST/TextNodeDumper.cpp
+++ b/clang/lib/AST/TextNodeDumper.cpp
@@ -1037,35 +1037,34 @@ void clang::TextNodeDumper::dumpTemplateSpecializationKind(
}
}
-void clang::TextNodeDumper::dumpNestedNameSpecifier(const NestedNameSpecifier *NNS) {
+void clang::TextNodeDumper::dumpNestedNameSpecifier(NestedNameSpecifier NNS) {
if (!NNS)
return;
AddChild([=] {
OS << "NestedNameSpecifier";
- switch (NNS->getKind()) {
- case NestedNameSpecifier::Identifier:
- OS << " Identifier";
- OS << " '" << NNS->getAsIdentifier()->getName() << "'";
- break;
- case NestedNameSpecifier::Namespace:
+ switch (NNS.getKind()) {
+ case NestedNameSpecifier::Kind::Namespace: {
+ auto [Namespace, Prefix] = NNS.getAsNamespaceAndPrefix();
OS << " "; // "Namespace" is printed as the decl kind.
- dumpBareDeclRef(NNS->getAsNamespace());
+ dumpBareDeclRef(Namespace);
+ dumpNestedNameSpecifier(Prefix);
break;
- case NestedNameSpecifier::TypeSpec:
+ }
+ case NestedNameSpecifier::Kind::Type:
OS << " TypeSpec";
- dumpType(QualType(NNS->getAsType(), 0));
+ dumpType(QualType(NNS.getAsType(), 0));
break;
- case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Kind::Global:
OS << " Global";
break;
- case NestedNameSpecifier::Super:
+ case NestedNameSpecifier::Kind::MicrosoftSuper:
OS << " Super";
break;
+ case NestedNameSpecifier::Kind::Null:
+ llvm_unreachable("unexpected null nested name specifier");
}
-
- dumpNestedNameSpecifier(NNS->getPrefix());
});
}
@@ -1401,8 +1400,8 @@ static void dumpBasePath(raw_ostream &OS, const CastExpr *Node) {
if (!First)
OS << " -> ";
- const auto *RD =
- cast<CXXRecordDecl>(Base->getType()->castAs<RecordType>()->getDecl());
+ const auto *RD = cast<CXXRecordDecl>(
+ Base->getType()->castAs<RecordType>()->getOriginalDecl());
if (Base->isVirtual())
OS << "virtual ";
@@ -2112,19 +2111,32 @@ void TextNodeDumper::VisitFunctionProtoType(const FunctionProtoType *T) {
}
void TextNodeDumper::VisitUnresolvedUsingType(const UnresolvedUsingType *T) {
+ if (ElaboratedTypeKeyword K = T->getKeyword();
+ K != ElaboratedTypeKeyword::None)
+ OS << ' ' << TypeWithKeyword::getKeywordName(K);
+ dumpNestedNameSpecifier(T->getQualifier());
dumpDeclRef(T->getDecl());
}
void TextNodeDumper::VisitUsingType(const UsingType *T) {
- dumpDeclRef(T->getFoundDecl());
- if (!T->typeMatchesDecl())
- OS << " divergent";
+ if (ElaboratedTypeKeyword K = T->getKeyword();
+ K != ElaboratedTypeKeyword::None)
+ OS << ' ' << TypeWithKeyword::getKeywordName(K);
+ dumpNestedNameSpecifier(T->getQualifier());
+ dumpDeclRef(T->getDecl());
+ dumpType(T->desugar());
}
void TextNodeDumper::VisitTypedefType(const TypedefType *T) {
+ if (ElaboratedTypeKeyword K = T->getKeyword();
+ K != ElaboratedTypeKeyword::None)
+ OS << ' ' << TypeWithKeyword::getKeywordName(K);
+ dumpNestedNameSpecifier(T->getQualifier());
dumpDeclRef(T->getDecl());
- if (!T->typeMatchesDecl())
+ if (!T->typeMatchesDecl()) {
OS << " divergent";
+ dumpType(T->desugar());
+ }
}
void TextNodeDumper::VisitUnaryTransformType(const UnaryTransformType *T) {
@@ -2138,7 +2150,17 @@ void TextNodeDumper::VisitUnaryTransformType(const UnaryTransformType *T) {
}
void TextNodeDumper::VisitTagType(const TagType *T) {
- dumpDeclRef(T->getDecl());
+ if (T->isCanonicalUnqualified())
+ OS << " canonical";
+ if (T->isTagOwned())
+ OS << " owns_tag";
+ if (T->isInjected())
+ OS << " injected";
+ if (ElaboratedTypeKeyword K = T->getKeyword();
+ K != ElaboratedTypeKeyword::None)
+ OS << ' ' << TypeWithKeyword::getKeywordName(K);
+ dumpNestedNameSpecifier(T->getQualifier());
+ dumpDeclRef(T->getOriginalDecl());
}
void TextNodeDumper::VisitTemplateTypeParmType(const TemplateTypeParmType *T) {
@@ -2182,12 +2204,15 @@ void TextNodeDumper::VisitTemplateSpecializationType(
const TemplateSpecializationType *T) {
if (T->isTypeAlias())
OS << " alias";
+ if (ElaboratedTypeKeyword K = T->getKeyword();
+ K != ElaboratedTypeKeyword::None)
+ OS << ' ' << TypeWithKeyword::getKeywordName(K);
dumpTemplateName(T->getTemplateName(), "name");
}
void TextNodeDumper::VisitInjectedClassNameType(
const InjectedClassNameType *T) {
- dumpDeclRef(T->getDecl());
+ dumpDeclRef(T->getOriginalDecl());
}
void TextNodeDumper::VisitObjCInterfaceType(const ObjCInterfaceType *T) {
@@ -2778,8 +2803,7 @@ void TextNodeDumper::VisitTemplateTemplateParmDecl(
void TextNodeDumper::VisitUsingDecl(const UsingDecl *D) {
OS << ' ';
- if (D->getQualifier())
- D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy());
+ D->getQualifier().print(OS, D->getASTContext().getPrintingPolicy());
OS << D->getDeclName();
dumpNestedNameSpecifier(D->getQualifier());
}
@@ -2792,16 +2816,14 @@ void TextNodeDumper::VisitUsingEnumDecl(const UsingEnumDecl *D) {
void TextNodeDumper::VisitUnresolvedUsingTypenameDecl(
const UnresolvedUsingTypenameDecl *D) {
OS << ' ';
- if (D->getQualifier())
- D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy());
+ D->getQualifier().print(OS, D->getASTContext().getPrintingPolicy());
OS << D->getDeclName();
}
void TextNodeDumper::VisitUnresolvedUsingValueDecl(
const UnresolvedUsingValueDecl *D) {
OS << ' ';
- if (D->getQualifier())
- D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy());
+ D->getQualifier().print(OS, D->getASTContext().getPrintingPolicy());
OS << D->getDeclName();
dumpType(D->getType());
}
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 141edc8..c382e58 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -109,12 +109,14 @@ bool Qualifiers::isTargetAddressSpaceSupersetOf(LangAS A, LangAS B,
const IdentifierInfo *QualType::getBaseTypeIdentifier() const {
const Type *ty = getTypePtr();
NamedDecl *ND = nullptr;
+ if (const auto *DNT = ty->getAs<DependentNameType>())
+ return DNT->getIdentifier();
if (ty->isPointerOrReferenceType())
return ty->getPointeeType().getBaseTypeIdentifier();
- else if (ty->isRecordType())
- ND = ty->castAs<RecordType>()->getDecl();
+ if (ty->isRecordType())
+ ND = ty->castAs<RecordType>()->getOriginalDecl();
else if (ty->isEnumeralType())
- ND = ty->castAs<EnumType>()->getDecl();
+ ND = ty->castAs<EnumType>()->getOriginalDecl();
else if (ty->getTypeClass() == Type::Typedef)
ND = ty->castAs<TypedefType>()->getDecl();
else if (ty->isArrayType())
@@ -671,13 +673,13 @@ const Type *Type::getUnqualifiedDesugaredType() const {
bool Type::isClassType() const {
if (const auto *RT = getAs<RecordType>())
- return RT->getDecl()->isClass();
+ return RT->getOriginalDecl()->isClass();
return false;
}
bool Type::isStructureType() const {
if (const auto *RT = getAs<RecordType>())
- return RT->getDecl()->isStruct();
+ return RT->getOriginalDecl()->isStruct();
return false;
}
@@ -685,7 +687,7 @@ bool Type::isStructureTypeWithFlexibleArrayMember() const {
const auto *RT = getAs<RecordType>();
if (!RT)
return false;
- const auto *Decl = RT->getDecl();
+ const auto *Decl = RT->getOriginalDecl()->getDefinitionOrSelf();
if (!Decl->isStruct())
return false;
return Decl->hasFlexibleArrayMember();
@@ -693,19 +695,21 @@ bool Type::isStructureTypeWithFlexibleArrayMember() const {
bool Type::isObjCBoxableRecordType() const {
if (const auto *RT = getAs<RecordType>())
- return RT->getDecl()->hasAttr<ObjCBoxableAttr>();
+ return RT->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->hasAttr<ObjCBoxableAttr>();
return false;
}
bool Type::isInterfaceType() const {
if (const auto *RT = getAs<RecordType>())
- return RT->getDecl()->isInterface();
+ return RT->getOriginalDecl()->isInterface();
return false;
}
bool Type::isStructureOrClassType() const {
if (const auto *RT = getAs<RecordType>()) {
- RecordDecl *RD = RT->getDecl();
+ RecordDecl *RD = RT->getOriginalDecl();
return RD->isStruct() || RD->isClass() || RD->isInterface();
}
return false;
@@ -719,7 +723,7 @@ bool Type::isVoidPointerType() const {
bool Type::isUnionType() const {
if (const auto *RT = getAs<RecordType>())
- return RT->getDecl()->isUnion();
+ return RT->getOriginalDecl()->isUnion();
return false;
}
@@ -736,7 +740,7 @@ bool Type::isComplexIntegerType() const {
bool Type::isScopedEnumeralType() const {
if (const auto *ET = getAs<EnumType>())
- return ET->getDecl()->isScoped();
+ return ET->getOriginalDecl()->isScoped();
return false;
}
@@ -770,13 +774,13 @@ QualType Type::getPointeeType() const {
const RecordType *Type::getAsStructureType() const {
// If this is directly a structure type, return it.
if (const auto *RT = dyn_cast<RecordType>(this)) {
- if (RT->getDecl()->isStruct())
+ if (RT->getOriginalDecl()->isStruct())
return RT;
}
// If the canonical form of this type isn't the right kind, reject it.
if (const auto *RT = dyn_cast<RecordType>(CanonicalType)) {
- if (!RT->getDecl()->isStruct())
+ if (!RT->getOriginalDecl()->isStruct())
return nullptr;
// If this is a typedef for a structure type, strip the typedef off without
@@ -789,13 +793,13 @@ const RecordType *Type::getAsStructureType() const {
const RecordType *Type::getAsUnionType() const {
// If this is directly a union type, return it.
if (const auto *RT = dyn_cast<RecordType>(this)) {
- if (RT->getDecl()->isUnion())
+ if (RT->getOriginalDecl()->isUnion())
return RT;
}
// If the canonical form of this type isn't the right kind, reject it.
if (const auto *RT = dyn_cast<RecordType>(CanonicalType)) {
- if (!RT->getDecl()->isUnion())
+ if (!RT->getOriginalDecl()->isUnion())
return nullptr;
// If this is a typedef for a union type, strip the typedef off without
@@ -1272,9 +1276,6 @@ public:
TRIVIAL_TYPE_CLASS(Record)
TRIVIAL_TYPE_CLASS(Enum)
- // FIXME: Non-trivial to implement, but important for C++
- SUGARED_TYPE_CLASS(Elaborated)
-
QualType VisitAttributedType(const AttributedType *T) {
QualType modifiedType = recurse(T->getModifiedType());
if (modifiedType.isNull())
@@ -1921,25 +1922,32 @@ const CXXRecordDecl *Type::getPointeeCXXRecordDecl() const {
return nullptr;
if (const auto *RT = PointeeType->getAs<RecordType>())
- return dyn_cast<CXXRecordDecl>(RT->getDecl());
+ return dyn_cast<CXXRecordDecl>(
+ RT->getOriginalDecl()->getDefinitionOrSelf());
return nullptr;
}
CXXRecordDecl *Type::getAsCXXRecordDecl() const {
- return dyn_cast_or_null<CXXRecordDecl>(getAsTagDecl());
+ const auto *TT = dyn_cast<TagType>(CanonicalType);
+ if (!isa_and_present<RecordType, InjectedClassNameType>(TT))
+ return nullptr;
+ auto *TD = TT->getOriginalDecl();
+ if (!isa<InjectedClassNameType>(TT) && !isa<CXXRecordDecl>(TD))
+ return nullptr;
+ return cast<CXXRecordDecl>(TD)->getDefinitionOrSelf();
}
RecordDecl *Type::getAsRecordDecl() const {
- return dyn_cast_or_null<RecordDecl>(getAsTagDecl());
+ const auto *TT = dyn_cast<TagType>(CanonicalType);
+ if (!isa_and_present<RecordType, InjectedClassNameType>(TT))
+ return nullptr;
+ return cast<RecordDecl>(TT->getOriginalDecl())->getDefinitionOrSelf();
}
TagDecl *Type::getAsTagDecl() const {
- if (const auto *TT = getAs<TagType>())
- return TT->getDecl();
- if (const auto *Injected = getAs<InjectedClassNameType>())
- return Injected->getDecl();
-
+ if (const auto *TT = dyn_cast<TagType>(CanonicalType))
+ return TT->getOriginalDecl()->getDefinitionOrSelf();
return nullptr;
}
@@ -1951,6 +1959,35 @@ Type::getAsNonAliasTemplateSpecializationType() const {
return TST;
}
+NestedNameSpecifier Type::getPrefix() const {
+ switch (getTypeClass()) {
+ case Type::DependentName:
+ return cast<DependentNameType>(this)->getQualifier();
+ case Type::TemplateSpecialization: {
+ QualifiedTemplateName *S = cast<TemplateSpecializationType>(this)
+ ->getTemplateName()
+ .getAsAdjustedQualifiedTemplateName();
+ return S ? S->getQualifier() : std::nullopt;
+ }
+ case Type::DependentTemplateSpecialization:
+ return cast<DependentTemplateSpecializationType>(this)
+ ->getDependentTemplateName()
+ .getQualifier();
+ case Type::Enum:
+ case Type::Record:
+ case Type::InjectedClassName:
+ return cast<TagType>(this)->getQualifier();
+ case Type::Typedef:
+ return cast<TypedefType>(this)->getQualifier();
+ case Type::UnresolvedUsing:
+ return cast<UnresolvedUsingType>(this)->getQualifier();
+ case Type::Using:
+ return cast<UsingType>(this)->getQualifier();
+ default:
+ return std::nullopt;
+ }
+}
+
bool Type::hasAttr(attr::Kind AK) const {
const Type *Cur = this;
while (const auto *AT = Cur->getAs<AttributedType>()) {
@@ -1989,10 +2026,6 @@ public:
return Visit(T->getReplacementType());
}
- Type *VisitElaboratedType(const ElaboratedType *T) {
- return Visit(T->getNamedType());
- }
-
Type *VisitPointerType(const PointerType *T) {
return Visit(T->getPointeeType());
}
@@ -2114,7 +2147,7 @@ bool Type::isIntegralType(const ASTContext &Ctx) const {
// Complete enum types are integral in C.
if (!Ctx.getLangOpts().CPlusPlus)
if (const auto *ET = dyn_cast<EnumType>(CanonicalType))
- return ET->getDecl()->isComplete();
+ return IsEnumDeclComplete(ET->getOriginalDecl());
return isBitIntType();
}
@@ -2131,7 +2164,7 @@ bool Type::isIntegralOrUnscopedEnumerationType() const {
bool Type::isUnscopedEnumerationType() const {
if (const auto *ET = dyn_cast<EnumType>(CanonicalType))
- return !ET->getDecl()->isScoped();
+ return !ET->getOriginalDecl()->isScoped();
return false;
}
@@ -2216,8 +2249,10 @@ bool Type::isSignedIntegerType() const {
if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) {
// Incomplete enum types are not treated as integer types.
// FIXME: In C++, enum types are never integer types.
- if (ET->getDecl()->isComplete() && !ET->getDecl()->isScoped())
- return ET->getDecl()->getIntegerType()->isSignedIntegerType();
+ const auto *ED = ET->getOriginalDecl()->getDefinitionOrSelf();
+ if (!ED->isComplete() || ED->isScoped())
+ return false;
+ return ED->getIntegerType()->isSignedIntegerType();
}
if (const auto *IT = dyn_cast<BitIntType>(CanonicalType))
@@ -2232,9 +2267,12 @@ bool Type::isSignedIntegerOrEnumerationType() const {
if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->isSignedInteger();
- if (const auto *ET = dyn_cast<EnumType>(CanonicalType);
- ET && ET->getDecl()->isComplete())
- return ET->getDecl()->getIntegerType()->isSignedIntegerType();
+ if (const auto *ET = dyn_cast<EnumType>(CanonicalType)) {
+ const auto *ED = ET->getOriginalDecl()->getDefinitionOrSelf();
+ if (!ED->isComplete())
+ return false;
+ return ED->getIntegerType()->isSignedIntegerType();
+ }
if (const auto *IT = dyn_cast<BitIntType>(CanonicalType))
return IT->isSigned();
@@ -2261,8 +2299,10 @@ bool Type::isUnsignedIntegerType() const {
if (const auto *ET = dyn_cast<EnumType>(CanonicalType)) {
// Incomplete enum types are not treated as integer types.
// FIXME: In C++, enum types are never integer types.
- if (ET->getDecl()->isComplete() && !ET->getDecl()->isScoped())
- return ET->getDecl()->getIntegerType()->isUnsignedIntegerType();
+ const auto *ED = ET->getOriginalDecl()->getDefinitionOrSelf();
+ if (!ED->isComplete() || ED->isScoped())
+ return false;
+ return ED->getIntegerType()->isUnsignedIntegerType();
}
if (const auto *IT = dyn_cast<BitIntType>(CanonicalType))
@@ -2277,9 +2317,12 @@ bool Type::isUnsignedIntegerOrEnumerationType() const {
if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->isUnsignedInteger();
- if (const auto *ET = dyn_cast<EnumType>(CanonicalType);
- ET && ET->getDecl()->isComplete())
- return ET->getDecl()->getIntegerType()->isUnsignedIntegerType();
+ if (const auto *ET = dyn_cast<EnumType>(CanonicalType)) {
+ const auto *ED = ET->getOriginalDecl()->getDefinitionOrSelf();
+ if (!ED->isComplete())
+ return false;
+ return ED->getIntegerType()->isUnsignedIntegerType();
+ }
if (const auto *IT = dyn_cast<BitIntType>(CanonicalType))
return IT->isUnsigned();
@@ -2328,8 +2371,10 @@ bool Type::isRealType() const {
if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() >= BuiltinType::Bool &&
BT->getKind() <= BuiltinType::Ibm128;
- if (const auto *ET = dyn_cast<EnumType>(CanonicalType))
- return ET->getDecl()->isComplete() && !ET->getDecl()->isScoped();
+ if (const auto *ET = dyn_cast<EnumType>(CanonicalType)) {
+ const auto *ED = ET->getOriginalDecl();
+ return !ED->isScoped() && ED->getDefinitionOrSelf()->isComplete();
+ }
return isBitIntType();
}
@@ -2337,14 +2382,16 @@ bool Type::isArithmeticType() const {
if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() >= BuiltinType::Bool &&
BT->getKind() <= BuiltinType::Ibm128;
- if (const auto *ET = dyn_cast<EnumType>(CanonicalType))
+ if (const auto *ET = dyn_cast<EnumType>(CanonicalType)) {
// GCC allows forward declaration of enum types (forbid by C99 6.7.2.3p2).
// If a body isn't seen by the time we get here, return false.
//
// C++0x: Enumerations are not arithmetic types. For now, just return
// false for scoped enumerations since that will disable any
// unwanted implicit conversions.
- return !ET->getDecl()->isScoped() && ET->getDecl()->isComplete();
+ const auto *ED = ET->getOriginalDecl();
+ return !ED->isScoped() && ED->getDefinitionOrSelf()->isComplete();
+ }
return isa<ComplexType>(CanonicalType) || isBitIntType();
}
@@ -2352,8 +2399,8 @@ bool Type::hasBooleanRepresentation() const {
if (const auto *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isBooleanType();
if (const auto *ET = dyn_cast<EnumType>(CanonicalType)) {
- return ET->getDecl()->isComplete() &&
- ET->getDecl()->getIntegerType()->isBooleanType();
+ const auto *ED = ET->getOriginalDecl()->getDefinitionOrSelf();
+ return ED->isComplete() && ED->getIntegerType()->isBooleanType();
}
if (const auto *IT = dyn_cast<BitIntType>(CanonicalType))
return IT->getNumBits() == 1;
@@ -2385,7 +2432,10 @@ Type::ScalarTypeKind Type::getScalarTypeKind() const {
} else if (isa<MemberPointerType>(T)) {
return STK_MemberPointer;
} else if (isa<EnumType>(T)) {
- assert(cast<EnumType>(T)->getDecl()->isComplete());
+ assert(cast<EnumType>(T)
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->isComplete());
return STK_Integral;
} else if (const auto *CT = dyn_cast<ComplexType>(T)) {
if (CT->getElementType()->isRealFloatingType())
@@ -2409,7 +2459,8 @@ Type::ScalarTypeKind Type::getScalarTypeKind() const {
/// includes union types.
bool Type::isAggregateType() const {
if (const auto *Record = dyn_cast<RecordType>(CanonicalType)) {
- if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(Record->getDecl()))
+ if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(
+ Record->getOriginalDecl()->getDefinitionOrSelf()))
return ClassDecl->isAggregate();
return true;
@@ -2443,7 +2494,8 @@ bool Type::isIncompleteType(NamedDecl **Def) const {
// be completed.
return isVoidType();
case Enum: {
- EnumDecl *EnumD = cast<EnumType>(CanonicalType)->getDecl();
+ EnumDecl *EnumD =
+ cast<EnumType>(CanonicalType)->getOriginalDecl()->getDefinitionOrSelf();
if (Def)
*Def = EnumD;
return !EnumD->isComplete();
@@ -2451,13 +2503,17 @@ bool Type::isIncompleteType(NamedDecl **Def) const {
case Record: {
// A tagged type (struct/union/enum/class) is incomplete if the decl is a
// forward declaration, but not a full definition (C99 6.2.5p22).
- RecordDecl *Rec = cast<RecordType>(CanonicalType)->getDecl();
+ RecordDecl *Rec = cast<RecordType>(CanonicalType)
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf();
if (Def)
*Def = Rec;
return !Rec->isCompleteDefinition();
}
case InjectedClassName: {
- CXXRecordDecl *Rec = cast<InjectedClassNameType>(CanonicalType)->getDecl();
+ CXXRecordDecl *Rec = cast<InjectedClassNameType>(CanonicalType)
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf();
if (!Rec->isBeingDefined())
return false;
if (Def)
@@ -2739,9 +2795,9 @@ bool QualType::isCXX98PODType(const ASTContext &Context) const {
return true;
case Type::Record:
- if (const auto *ClassDecl =
- dyn_cast<CXXRecordDecl>(cast<RecordType>(CanonicalType)->getDecl()))
- return ClassDecl->isPOD();
+ if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(
+ cast<RecordType>(CanonicalType)->getOriginalDecl()))
+ return ClassDecl->getDefinitionOrSelf()->isPOD();
// C struct/union is POD.
return true;
@@ -2782,7 +2838,8 @@ bool QualType::isTrivialType(const ASTContext &Context) const {
if (CanonicalType->isScalarType() || CanonicalType->isVectorType())
return true;
if (const auto *RT = CanonicalType->getAs<RecordType>()) {
- if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
+ if (const auto *ClassDecl =
+ dyn_cast<CXXRecordDecl>(RT->getOriginalDecl())) {
// C++20 [class]p6:
// A trivial class is a class that is trivially copyable, and
// has one or more eligible default constructors such that each is
@@ -2841,14 +2898,17 @@ static bool isTriviallyCopyableTypeImpl(const QualType &type,
return true;
if (const auto *RT = CanonicalType->getAs<RecordType>()) {
- if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
+ if (const auto *ClassDecl =
+ dyn_cast<CXXRecordDecl>(RT->getOriginalDecl())) {
if (IsCopyConstructible) {
return ClassDecl->isTriviallyCopyConstructible();
} else {
return ClassDecl->isTriviallyCopyable();
}
}
- return !RT->getDecl()->isNonTrivialToPrimitiveCopy();
+ return !RT->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->isNonTrivialToPrimitiveCopy();
}
// No other types can match.
return false;
@@ -2938,7 +2998,9 @@ QualType::PrimitiveDefaultInitializeKind
QualType::isNonTrivialToPrimitiveDefaultInitialize() const {
if (const auto *RT =
getTypePtr()->getBaseElementTypeUnsafe()->getAs<RecordType>())
- if (RT->getDecl()->isNonTrivialToPrimitiveDefaultInitialize())
+ if (RT->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->isNonTrivialToPrimitiveDefaultInitialize())
return PDIK_Struct;
switch (getQualifiers().getObjCLifetime()) {
@@ -2954,7 +3016,9 @@ QualType::isNonTrivialToPrimitiveDefaultInitialize() const {
QualType::PrimitiveCopyKind QualType::isNonTrivialToPrimitiveCopy() const {
if (const auto *RT =
getTypePtr()->getBaseElementTypeUnsafe()->getAs<RecordType>())
- if (RT->getDecl()->isNonTrivialToPrimitiveCopy())
+ if (RT->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->isNonTrivialToPrimitiveCopy())
return PCK_Struct;
Qualifiers Qs = getQualifiers();
@@ -3022,8 +3086,8 @@ bool Type::isLiteralType(const ASTContext &Ctx) const {
// -- all non-static data members and base classes of literal types
//
// We resolve DR1361 by ignoring the second bullet.
- if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl()))
- return ClassDecl->isLiteral();
+ if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getOriginalDecl()))
+ return ClassDecl->getDefinitionOrSelf()->isLiteral();
return true;
}
@@ -3076,8 +3140,8 @@ bool Type::isStandardLayoutType() const {
if (BaseTy->isScalarType() || BaseTy->isVectorType())
return true;
if (const auto *RT = BaseTy->getAs<RecordType>()) {
- if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl()))
- if (!ClassDecl->isStandardLayout())
+ if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getOriginalDecl()))
+ if (!ClassDecl->getDefinitionOrSelf()->isStandardLayout())
return false;
// Default to 'true' for non-C++ class types.
@@ -3119,7 +3183,9 @@ bool QualType::isCXX11PODType(const ASTContext &Context) const {
if (BaseTy->isScalarType() || BaseTy->isVectorType())
return true;
if (const auto *RT = BaseTy->getAs<RecordType>()) {
- if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
+ if (const auto *ClassDecl =
+ dyn_cast<CXXRecordDecl>(RT->getOriginalDecl())) {
+ ClassDecl = ClassDecl->getDefinitionOrSelf();
// C++11 [class]p10:
// A POD struct is a non-union class that is both a trivial class [...]
if (!ClassDecl->isTrivial())
@@ -3159,8 +3225,9 @@ bool Type::isNothrowT() const {
bool Type::isAlignValT() const {
if (const auto *ET = getAs<EnumType>()) {
- IdentifierInfo *II = ET->getDecl()->getIdentifier();
- if (II && II->isStr("align_val_t") && ET->getDecl()->isInStdNamespace())
+ const auto *ED = ET->getOriginalDecl();
+ IdentifierInfo *II = ED->getIdentifier();
+ if (II && II->isStr("align_val_t") && ED->isInStdNamespace())
return true;
}
return false;
@@ -3168,8 +3235,9 @@ bool Type::isAlignValT() const {
bool Type::isStdByteType() const {
if (const auto *ET = getAs<EnumType>()) {
- IdentifierInfo *II = ET->getDecl()->getIdentifier();
- if (II && II->isStr("byte") && ET->getDecl()->isInStdNamespace())
+ const auto *ED = ET->getOriginalDecl();
+ IdentifierInfo *II = ED->getIdentifier();
+ if (II && II->isStr("byte") && ED->isInStdNamespace())
return true;
}
return false;
@@ -3188,7 +3256,6 @@ bool Type::isSpecifierType() const {
case TemplateTypeParm:
case SubstTemplateTypeParm:
case TemplateSpecialization:
- case Elaborated:
case DependentName:
case DependentTemplateSpecialization:
case ObjCInterface:
@@ -3199,8 +3266,7 @@ bool Type::isSpecifierType() const {
}
}
-ElaboratedTypeKeyword
-TypeWithKeyword::getKeywordForTypeSpec(unsigned TypeSpec) {
+ElaboratedTypeKeyword KeywordHelpers::getKeywordForTypeSpec(unsigned TypeSpec) {
switch (TypeSpec) {
default:
return ElaboratedTypeKeyword::None;
@@ -3219,7 +3285,7 @@ TypeWithKeyword::getKeywordForTypeSpec(unsigned TypeSpec) {
}
}
-TagTypeKind TypeWithKeyword::getTagTypeKindForTypeSpec(unsigned TypeSpec) {
+TagTypeKind KeywordHelpers::getTagTypeKindForTypeSpec(unsigned TypeSpec) {
switch (TypeSpec) {
case TST_class:
return TagTypeKind::Class;
@@ -3237,7 +3303,7 @@ TagTypeKind TypeWithKeyword::getTagTypeKindForTypeSpec(unsigned TypeSpec) {
}
ElaboratedTypeKeyword
-TypeWithKeyword::getKeywordForTagTypeKind(TagTypeKind Kind) {
+KeywordHelpers::getKeywordForTagTypeKind(TagTypeKind Kind) {
switch (Kind) {
case TagTypeKind::Class:
return ElaboratedTypeKeyword::Class;
@@ -3254,7 +3320,7 @@ TypeWithKeyword::getKeywordForTagTypeKind(TagTypeKind Kind) {
}
TagTypeKind
-TypeWithKeyword::getTagTypeKindForKeyword(ElaboratedTypeKeyword Keyword) {
+KeywordHelpers::getTagTypeKindForKeyword(ElaboratedTypeKeyword Keyword) {
switch (Keyword) {
case ElaboratedTypeKeyword::Class:
return TagTypeKind::Class;
@@ -3273,7 +3339,7 @@ TypeWithKeyword::getTagTypeKindForKeyword(ElaboratedTypeKeyword Keyword) {
llvm_unreachable("Unknown elaborated type keyword.");
}
-bool TypeWithKeyword::KeywordIsTagTypeKind(ElaboratedTypeKeyword Keyword) {
+bool KeywordHelpers::KeywordIsTagTypeKind(ElaboratedTypeKeyword Keyword) {
switch (Keyword) {
case ElaboratedTypeKeyword::None:
case ElaboratedTypeKeyword::Typename:
@@ -3288,7 +3354,7 @@ bool TypeWithKeyword::KeywordIsTagTypeKind(ElaboratedTypeKeyword Keyword) {
llvm_unreachable("Unknown elaborated type keyword.");
}
-StringRef TypeWithKeyword::getKeywordName(ElaboratedTypeKeyword Keyword) {
+StringRef KeywordHelpers::getKeywordName(ElaboratedTypeKeyword Keyword) {
switch (Keyword) {
case ElaboratedTypeKeyword::None:
return {};
@@ -3338,13 +3404,21 @@ void DependentTemplateSpecializationType::Profile(
bool Type::isElaboratedTypeSpecifier() const {
ElaboratedTypeKeyword Keyword;
- if (const auto *Elab = dyn_cast<ElaboratedType>(this))
- Keyword = Elab->getKeyword();
+ if (const auto *TST = dyn_cast<TemplateSpecializationType>(this))
+ Keyword = TST->getKeyword();
else if (const auto *DepName = dyn_cast<DependentNameType>(this))
Keyword = DepName->getKeyword();
else if (const auto *DepTST =
dyn_cast<DependentTemplateSpecializationType>(this))
Keyword = DepTST->getKeyword();
+ else if (const auto *T = dyn_cast<TagType>(this))
+ Keyword = T->getKeyword();
+ else if (const auto *T = dyn_cast<TypedefType>(this))
+ Keyword = T->getKeyword();
+ else if (const auto *T = dyn_cast<UnresolvedUsingType>(this))
+ Keyword = T->getKeyword();
+ else if (const auto *T = dyn_cast<UsingType>(this))
+ Keyword = T->getKeyword();
else
return false;
@@ -4011,34 +4085,53 @@ StringRef CountAttributedType::getAttributeName(bool WithMacroPrefix) const {
#undef ENUMERATE_ATTRS
}
-TypedefType::TypedefType(TypeClass tc, const TypedefNameDecl *D,
- QualType UnderlyingType, bool HasTypeDifferentFromDecl)
- : Type(tc, UnderlyingType.getCanonicalType(),
- toSemanticDependence(UnderlyingType->getDependence())),
+TypedefType::TypedefType(TypeClass TC, ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifier Qualifier,
+ const TypedefNameDecl *D, QualType UnderlyingType,
+ bool HasTypeDifferentFromDecl)
+ : TypeWithKeyword(
+ Keyword, TC, UnderlyingType.getCanonicalType(),
+ toSemanticDependence(UnderlyingType->getDependence()) |
+ (Qualifier
+ ? toTypeDependence(Qualifier.getDependence() &
+ ~NestedNameSpecifierDependence::Dependent)
+ : TypeDependence{})),
Decl(const_cast<TypedefNameDecl *>(D)) {
- TypedefBits.hasTypeDifferentFromDecl = HasTypeDifferentFromDecl;
- if (!typeMatchesDecl())
- *getTrailingObjects() = UnderlyingType;
+ if ((TypedefBits.hasQualifier = !!Qualifier))
+ *getTrailingObjects<NestedNameSpecifier>() = Qualifier;
+ if ((TypedefBits.hasTypeDifferentFromDecl = HasTypeDifferentFromDecl))
+ *getTrailingObjects<QualType>() = UnderlyingType;
}
QualType TypedefType::desugar() const {
- return typeMatchesDecl() ? Decl->getUnderlyingType() : *getTrailingObjects();
-}
-
-UsingType::UsingType(const UsingShadowDecl *Found, QualType Underlying,
- QualType Canon)
- : Type(Using, Canon, toSemanticDependence(Canon->getDependence())),
- Found(const_cast<UsingShadowDecl *>(Found)) {
- UsingBits.hasTypeDifferentFromDecl = !Underlying.isNull();
- if (!typeMatchesDecl())
- *getTrailingObjects() = Underlying;
-}
-
-QualType UsingType::getUnderlyingType() const {
- return typeMatchesDecl()
- ? QualType(
- cast<TypeDecl>(Found->getTargetDecl())->getTypeForDecl(), 0)
- : *getTrailingObjects();
+ return typeMatchesDecl() ? Decl->getUnderlyingType()
+ : *getTrailingObjects<QualType>();
+}
+
+UnresolvedUsingType::UnresolvedUsingType(ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifier Qualifier,
+ const UnresolvedUsingTypenameDecl *D,
+ const Type *CanonicalType)
+ : TypeWithKeyword(
+ Keyword, UnresolvedUsing, QualType(CanonicalType, 0),
+ TypeDependence::DependentInstantiation |
+ (Qualifier
+ ? toTypeDependence(Qualifier.getDependence() &
+ ~NestedNameSpecifierDependence::Dependent)
+ : TypeDependence{})),
+ Decl(const_cast<UnresolvedUsingTypenameDecl *>(D)) {
+ if ((UnresolvedUsingBits.hasQualifier = !!Qualifier))
+ *getTrailingObjects<NestedNameSpecifier>() = Qualifier;
+}
+
+UsingType::UsingType(ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifier Qualifier, const UsingShadowDecl *D,
+ QualType UnderlyingType)
+ : TypeWithKeyword(Keyword, Using, UnderlyingType.getCanonicalType(),
+ toSemanticDependence(UnderlyingType->getDependence())),
+ D(const_cast<UsingShadowDecl *>(D)), UnderlyingType(UnderlyingType) {
+ if ((UsingBits.hasQualifier = !!Qualifier))
+ *getTrailingObjects() = Qualifier;
}
QualType MacroQualifiedType::desugar() const { return getUnderlyingType(); }
@@ -4212,24 +4305,79 @@ UnaryTransformType::UnaryTransformType(QualType BaseType,
: Type(UnaryTransform, CanonicalType, BaseType->getDependence()),
BaseType(BaseType), UnderlyingType(UnderlyingType), UKind(UKind) {}
-TagType::TagType(TypeClass TC, const TagDecl *D, QualType can)
- : Type(TC, can,
- D->isDependentType() ? TypeDependence::DependentInstantiation
- : TypeDependence::None),
- decl(const_cast<TagDecl *>(D)) {}
-
-static TagDecl *getInterestingTagDecl(TagDecl *decl) {
- for (auto *I : decl->redecls()) {
- if (I->isCompleteDefinition() || I->isBeingDefined())
- return I;
+TagType::TagType(TypeClass TC, ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifier Qualifier, const TagDecl *Tag,
+ bool OwnsTag, bool ISInjected, const Type *CanonicalType)
+ : TypeWithKeyword(
+ Keyword, TC, QualType(CanonicalType, 0),
+ (Tag->isDependentType() ? TypeDependence::DependentInstantiation
+ : TypeDependence::None) |
+ (Qualifier
+ ? toTypeDependence(Qualifier.getDependence() &
+ ~NestedNameSpecifierDependence::Dependent)
+ : TypeDependence{})),
+ decl(const_cast<TagDecl *>(Tag)) {
+ if ((TagTypeBits.HasQualifier = !!Qualifier))
+ getTrailingQualifier() = Qualifier;
+ TagTypeBits.OwnsTag = !!OwnsTag;
+ TagTypeBits.IsInjected = ISInjected;
+}
+
+void *TagType::getTrailingPointer() const {
+ switch (getTypeClass()) {
+ case Type::Enum:
+ return const_cast<EnumType *>(cast<EnumType>(this) + 1);
+ case Type::Record:
+ return const_cast<RecordType *>(cast<RecordType>(this) + 1);
+ case Type::InjectedClassName:
+ return const_cast<InjectedClassNameType *>(
+ cast<InjectedClassNameType>(this) + 1);
+ default:
+ llvm_unreachable("unexpected type class");
}
- // If there's no definition (not even in progress), return what we have.
- return decl;
}
-TagDecl *TagType::getDecl() const { return getInterestingTagDecl(decl); }
+NestedNameSpecifier &TagType::getTrailingQualifier() const {
+ assert(TagTypeBits.HasQualifier);
+ return *reinterpret_cast<NestedNameSpecifier *>(llvm::alignAddr(
+ getTrailingPointer(), llvm::Align::Of<NestedNameSpecifier *>()));
+}
+
+NestedNameSpecifier TagType::getQualifier() const {
+ return TagTypeBits.HasQualifier ? getTrailingQualifier() : std::nullopt;
+}
+
+ClassTemplateDecl *TagType::getTemplateDecl() const {
+ auto *Decl = dyn_cast<CXXRecordDecl>(decl);
+ if (!Decl)
+ return nullptr;
+ if (auto *RD = dyn_cast<ClassTemplateSpecializationDecl>(Decl))
+ return RD->getSpecializedTemplate();
+ return Decl->getDescribedClassTemplate();
+}
-bool TagType::isBeingDefined() const { return getDecl()->isBeingDefined(); }
+TemplateName TagType::getTemplateName(const ASTContext &Ctx) const {
+ auto *TD = getTemplateDecl();
+ if (!TD)
+ return TemplateName();
+ if (isCanonicalUnqualified())
+ return TemplateName(TD);
+ return Ctx.getQualifiedTemplateName(getQualifier(), /*TemplateKeyword=*/false,
+ TemplateName(TD));
+}
+
+ArrayRef<TemplateArgument>
+TagType::getTemplateArgs(const ASTContext &Ctx) const {
+ auto *Decl = dyn_cast<CXXRecordDecl>(decl);
+ if (!Decl)
+ return {};
+
+ if (auto *RD = dyn_cast<ClassTemplateSpecializationDecl>(Decl))
+ return RD->getTemplateArgs().asArray();
+ if (ClassTemplateDecl *TD = Decl->getDescribedClassTemplate())
+ return TD->getTemplateParameters()->getInjectedTemplateArgs(Ctx);
+ return {};
+}
bool RecordType::hasConstFields() const {
std::vector<const RecordType *> RecordTypeList;
@@ -4237,8 +4385,10 @@ bool RecordType::hasConstFields() const {
unsigned NextToCheckIndex = 0;
while (RecordTypeList.size() > NextToCheckIndex) {
- for (FieldDecl *FD :
- RecordTypeList[NextToCheckIndex]->getDecl()->fields()) {
+ for (FieldDecl *FD : RecordTypeList[NextToCheckIndex]
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->fields()) {
QualType FieldTy = FD->getType();
if (FieldTy.isConstQualified())
return true;
@@ -4253,6 +4403,13 @@ bool RecordType::hasConstFields() const {
return false;
}
+InjectedClassNameType::InjectedClassNameType(ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifier Qualifier,
+ const TagDecl *TD, bool IsInjected,
+ const Type *CanonicalType)
+ : TagType(TypeClass::InjectedClassName, Keyword, Qualifier, TD,
+ /*OwnsTag=*/false, IsInjected, CanonicalType) {}
+
AttributedType::AttributedType(QualType canon, const Attr *attr,
QualType modified, QualType equivalent)
: AttributedType(canon, attr->getKind(), attr, modified, equivalent) {}
@@ -4340,10 +4497,6 @@ bool AttributedType::isCallingConv() const {
llvm_unreachable("invalid attr kind");
}
-CXXRecordDecl *InjectedClassNameType::getDecl() const {
- return cast<CXXRecordDecl>(getInterestingTagDecl(Decl));
-}
-
IdentifierInfo *TemplateTypeParmType::getIdentifier() const {
return isCanonicalUnqualified() ? nullptr : getDecl()->getIdentifier();
}
@@ -4467,16 +4620,17 @@ bool TemplateSpecializationType::anyInstantiationDependentTemplateArguments(
}
TemplateSpecializationType::TemplateSpecializationType(
- TemplateName T, bool IsAlias, ArrayRef<TemplateArgument> Args,
- QualType Underlying)
- : Type(TemplateSpecialization,
- Underlying.isNull() ? QualType(this, 0)
- : Underlying.getCanonicalType(),
- (Underlying.isNull()
- ? TypeDependence::DependentInstantiation
- : toSemanticDependence(Underlying->getDependence())) |
- (toTypeDependence(T.getDependence()) &
- TypeDependence::UnexpandedPack)),
+ ElaboratedTypeKeyword Keyword, TemplateName T, bool IsAlias,
+ ArrayRef<TemplateArgument> Args, QualType Underlying)
+ : TypeWithKeyword(
+ Keyword, TemplateSpecialization,
+ Underlying.isNull() ? QualType(this, 0)
+ : Underlying.getCanonicalType(),
+ (Underlying.isNull()
+ ? TypeDependence::DependentInstantiation
+ : toSemanticDependence(Underlying->getDependence())) |
+ (toTypeDependence(T.getDependence()) &
+ TypeDependence::UnexpandedPack)),
Template(T) {
TemplateSpecializationTypeBits.NumArgs = Args.size();
TemplateSpecializationTypeBits.TypeAlias = IsAlias;
@@ -4699,7 +4853,8 @@ static CachedProperties computeCachedProperties(const Type *T) {
case Type::Record:
case Type::Enum: {
- const TagDecl *Tag = cast<TagType>(T)->getDecl();
+ const TagDecl *Tag =
+ cast<TagType>(T)->getOriginalDecl()->getDefinitionOrSelf();
// C++ [basic.link]p8:
// - it is a class or enumeration type that is named (or has a name
@@ -4726,12 +4881,9 @@ static CachedProperties computeCachedProperties(const Type *T) {
case Type::MemberPointer: {
const auto *MPT = cast<MemberPointerType>(T);
CachedProperties Cls = [&] {
- if (auto *RD = MPT->getMostRecentCXXRecordDecl())
- return Cache::get(QualType(RD->getTypeForDecl(), 0));
- if (const Type *T = MPT->getQualifier()->getAsType())
- return Cache::get(T);
- // Treat as a dependent type.
- return CachedProperties(Linkage::External, false);
+ if (MPT->isSugared())
+ MPT = cast<MemberPointerType>(MPT->getCanonicalTypeInternal());
+ return Cache::get(MPT->getQualifier().getAsType());
}();
return merge(Cls, Cache::get(MPT->getPointeeType()));
}
@@ -4811,7 +4963,8 @@ LinkageInfo LinkageComputer::computeTypeLinkageInfo(const Type *T) {
case Type::Record:
case Type::Enum:
- return getDeclLinkageAndVisibility(cast<TagType>(T)->getDecl());
+ return getDeclLinkageAndVisibility(
+ cast<TagType>(T)->getOriginalDecl()->getDefinitionOrSelf());
case Type::Complex:
return computeTypeLinkageInfo(cast<ComplexType>(T)->getElementType());
@@ -4827,8 +4980,8 @@ LinkageInfo LinkageComputer::computeTypeLinkageInfo(const Type *T) {
LinkageInfo LV;
if (auto *D = MPT->getMostRecentCXXRecordDecl()) {
LV.merge(getDeclLinkageAndVisibility(D));
- } else if (auto *Ty = MPT->getQualifier()->getAsType()) {
- LV.merge(computeTypeLinkageInfo(Ty));
+ } else {
+ LV.merge(computeTypeLinkageInfo(MPT->getQualifier().getAsType()));
}
LV.merge(computeTypeLinkageInfo(MPT->getPointeeType()));
return LV;
@@ -5014,7 +5167,7 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const {
llvm_unreachable("unknown builtin type");
case Type::Record: {
- const RecordDecl *RD = cast<RecordType>(type)->getDecl();
+ const RecordDecl *RD = cast<RecordType>(type)->getOriginalDecl();
// For template specializations, look only at primary template attributes.
// This is a consistent regardless of whether the instantiation is known.
if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD))
@@ -5212,14 +5365,18 @@ bool Type::isCARCBridgableType() const {
/// Check if the specified type is the CUDA device builtin surface type.
bool Type::isCUDADeviceBuiltinSurfaceType() const {
if (const auto *RT = getAs<RecordType>())
- return RT->getDecl()->hasAttr<CUDADeviceBuiltinSurfaceTypeAttr>();
+ return RT->getOriginalDecl()
+ ->getMostRecentDecl()
+ ->hasAttr<CUDADeviceBuiltinSurfaceTypeAttr>();
return false;
}
/// Check if the specified type is the CUDA device builtin texture type.
bool Type::isCUDADeviceBuiltinTextureType() const {
if (const auto *RT = getAs<RecordType>())
- return RT->getDecl()->hasAttr<CUDADeviceBuiltinTextureTypeAttr>();
+ return RT->getOriginalDecl()
+ ->getMostRecentDecl()
+ ->hasAttr<CUDADeviceBuiltinTextureTypeAttr>();
return false;
}
@@ -5246,6 +5403,15 @@ bool Type::isHLSLResourceRecord() const {
return HLSLAttributedResourceType::findHandleTypeOnResource(this) != nullptr;
}
+bool Type::isHLSLResourceRecordArray() const {
+ const Type *Ty = getUnqualifiedDesugaredType();
+ if (!Ty->isArrayType())
+ return false;
+ while (isa<ConstantArrayType>(Ty))
+ Ty = Ty->getArrayElementTypeNoTypeQual();
+ return Ty->isHLSLResourceRecord();
+}
+
bool Type::isHLSLIntangibleType() const {
const Type *Ty = getUnqualifiedDesugaredType();
@@ -5283,7 +5449,7 @@ QualType::DestructionKind QualType::isDestructedTypeImpl(QualType type) {
}
if (const auto *RT = type->getBaseElementTypeUnsafe()->getAs<RecordType>()) {
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl();
if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
/// Check if this is a C++ object with a non-trivial destructor.
if (CXXRD->hasDefinition() && !CXXRD->hasTrivialDestructor())
@@ -5291,7 +5457,7 @@ QualType::DestructionKind QualType::isDestructedTypeImpl(QualType type) {
} else {
/// Check if this is a C struct that is non-trivial to destroy or an array
/// that contains such a struct.
- if (RD->isNonTrivialToPrimitiveDestroy())
+ if (RD->getDefinitionOrSelf()->isNonTrivialToPrimitiveDestroy())
return DK_nontrivial_c_struct;
}
}
@@ -5301,16 +5467,16 @@ QualType::DestructionKind QualType::isDestructedTypeImpl(QualType type) {
bool MemberPointerType::isSugared() const {
CXXRecordDecl *D1 = getMostRecentCXXRecordDecl(),
- *D2 = getQualifier()->getAsRecordDecl();
+ *D2 = getQualifier().getAsRecordDecl();
assert(!D1 == !D2);
return D1 != D2 && D1->getCanonicalDecl() != D2->getCanonicalDecl();
}
void MemberPointerType::Profile(llvm::FoldingSetNodeID &ID, QualType Pointee,
- const NestedNameSpecifier *Qualifier,
+ const NestedNameSpecifier Qualifier,
const CXXRecordDecl *Cls) {
ID.AddPointer(Pointee.getAsOpaquePtr());
- ID.AddPointer(Qualifier);
+ Qualifier.Profile(ID);
if (Cls)
ID.AddPointer(Cls->getCanonicalDecl());
}
@@ -5318,14 +5484,14 @@ void MemberPointerType::Profile(llvm::FoldingSetNodeID &ID, QualType Pointee,
CXXRecordDecl *MemberPointerType::getCXXRecordDecl() const {
return dyn_cast<MemberPointerType>(getCanonicalTypeInternal())
->getQualifier()
- ->getAsRecordDecl();
+ .getAsRecordDecl();
}
CXXRecordDecl *MemberPointerType::getMostRecentCXXRecordDecl() const {
auto *RD = getCXXRecordDecl();
if (!RD)
return nullptr;
- return RD->getMostRecentNonInjectedDecl();
+ return RD->getMostRecentDecl();
}
void clang::FixedPointValueToString(SmallVectorImpl<char> &Str,
diff --git a/clang/lib/AST/TypeLoc.cpp b/clang/lib/AST/TypeLoc.cpp
index 5c45c59..fbe8772 100644
--- a/clang/lib/AST/TypeLoc.cpp
+++ b/clang/lib/AST/TypeLoc.cpp
@@ -195,15 +195,6 @@ SourceLocation TypeLoc::getBeginLoc() const {
TypeLoc LeftMost = Cur;
while (true) {
switch (Cur.getTypeLocClass()) {
- case Elaborated:
- if (Cur.getLocalSourceRange().getBegin().isValid()) {
- LeftMost = Cur;
- break;
- }
- Cur = Cur.getNextTypeLoc();
- if (Cur.isNull())
- break;
- continue;
case FunctionProto:
if (Cur.castAs<FunctionProtoTypeLoc>().getTypePtr()
->hasTrailingReturn()) {
@@ -275,7 +266,6 @@ SourceLocation TypeLoc::getEndLoc() const {
Last = Cur;
break;
case Qualified:
- case Elaborated:
break;
}
Cur = Cur.getNextTypeLoc();
@@ -313,9 +303,8 @@ bool TypeSpecTypeLoc::isKind(const TypeLoc &TL) {
}
bool TagTypeLoc::isDefinition() const {
- TagDecl *D = getDecl();
- return D->isCompleteDefinition() &&
- (D->getIdentifier() == nullptr || D->getLocation() == getNameLoc());
+ return getTypePtr()->isTagOwned() &&
+ getOriginalDecl()->isCompleteDefinition();
}
// Reimplemented to account for GNU/C++ extension
@@ -482,6 +471,134 @@ TypeLoc TypeLoc::findExplicitQualifierLoc() const {
return {};
}
+NestedNameSpecifierLoc TypeLoc::getPrefix() const {
+ switch (getTypeLocClass()) {
+ case TypeLoc::DependentName:
+ return castAs<DependentNameTypeLoc>().getQualifierLoc();
+ case TypeLoc::TemplateSpecialization:
+ return castAs<TemplateSpecializationTypeLoc>().getQualifierLoc();
+ case TypeLoc::DependentTemplateSpecialization:
+ return castAs<DependentTemplateSpecializationTypeLoc>().getQualifierLoc();
+ case TypeLoc::DeducedTemplateSpecialization:
+ return castAs<DeducedTemplateSpecializationTypeLoc>().getQualifierLoc();
+ case TypeLoc::Enum:
+ case TypeLoc::Record:
+ case TypeLoc::InjectedClassName:
+ return castAs<TagTypeLoc>().getQualifierLoc();
+ case TypeLoc::Typedef:
+ return castAs<TypedefTypeLoc>().getQualifierLoc();
+ case TypeLoc::UnresolvedUsing:
+ return castAs<UnresolvedUsingTypeLoc>().getQualifierLoc();
+ case TypeLoc::Using:
+ return castAs<UsingTypeLoc>().getQualifierLoc();
+ default:
+ return NestedNameSpecifierLoc();
+ }
+}
+
+SourceLocation TypeLoc::getNonPrefixBeginLoc() const {
+ switch (getTypeLocClass()) {
+ case TypeLoc::TemplateSpecialization: {
+ auto TL = castAs<TemplateSpecializationTypeLoc>();
+ SourceLocation Loc = TL.getTemplateKeywordLoc();
+ if (!Loc.isValid())
+ Loc = TL.getTemplateNameLoc();
+ return Loc;
+ }
+ case TypeLoc::DependentTemplateSpecialization: {
+ auto TL = castAs<DependentTemplateSpecializationTypeLoc>();
+ SourceLocation Loc = TL.getTemplateKeywordLoc();
+ if (!Loc.isValid())
+ Loc = TL.getTemplateNameLoc();
+ return Loc;
+ }
+ case TypeLoc::DeducedTemplateSpecialization: {
+ auto TL = castAs<DeducedTemplateSpecializationTypeLoc>();
+ SourceLocation Loc = TL.getTemplateKeywordLoc();
+ if (!Loc.isValid())
+ Loc = TL.getTemplateNameLoc();
+ return Loc;
+ }
+ case TypeLoc::DependentName:
+ return castAs<DependentNameTypeLoc>().getNameLoc();
+ case TypeLoc::Enum:
+ case TypeLoc::Record:
+ case TypeLoc::InjectedClassName:
+ return castAs<TagTypeLoc>().getNameLoc();
+ case TypeLoc::Typedef:
+ return castAs<TypedefTypeLoc>().getNameLoc();
+ case TypeLoc::UnresolvedUsing:
+ return castAs<UnresolvedUsingTypeLoc>().getNameLoc();
+ case TypeLoc::Using:
+ return castAs<UsingTypeLoc>().getNameLoc();
+ default:
+ return getBeginLoc();
+ }
+}
+
+SourceLocation TypeLoc::getNonElaboratedBeginLoc() const {
+ // For elaborated types (e.g. `struct a::A`) we want the portion after the
+ // `struct` but including the namespace qualifier, `a::`.
+ switch (getTypeLocClass()) {
+ case TypeLoc::Qualified:
+ return castAs<QualifiedTypeLoc>()
+ .getUnqualifiedLoc()
+ .getNonElaboratedBeginLoc();
+ case TypeLoc::TemplateSpecialization: {
+ auto T = castAs<TemplateSpecializationTypeLoc>();
+ if (NestedNameSpecifierLoc QualifierLoc = T.getQualifierLoc())
+ return QualifierLoc.getBeginLoc();
+ return T.getTemplateNameLoc();
+ }
+ case TypeLoc::DependentTemplateSpecialization: {
+ auto T = castAs<DependentTemplateSpecializationTypeLoc>();
+ if (NestedNameSpecifierLoc QualifierLoc = T.getQualifierLoc())
+ return QualifierLoc.getBeginLoc();
+ return T.getTemplateNameLoc();
+ }
+ case TypeLoc::DeducedTemplateSpecialization: {
+ auto T = castAs<DeducedTemplateSpecializationTypeLoc>();
+ if (NestedNameSpecifierLoc QualifierLoc = T.getQualifierLoc())
+ return QualifierLoc.getBeginLoc();
+ return T.getTemplateNameLoc();
+ }
+ case TypeLoc::DependentName: {
+ auto T = castAs<DependentNameTypeLoc>();
+ if (NestedNameSpecifierLoc QualifierLoc = T.getQualifierLoc())
+ return QualifierLoc.getBeginLoc();
+ return T.getNameLoc();
+ }
+ case TypeLoc::Enum:
+ case TypeLoc::Record:
+ case TypeLoc::InjectedClassName: {
+ auto T = castAs<TagTypeLoc>();
+ if (NestedNameSpecifierLoc QualifierLoc = T.getQualifierLoc())
+ return QualifierLoc.getBeginLoc();
+ return T.getNameLoc();
+ }
+ case TypeLoc::Typedef: {
+ auto T = castAs<TypedefTypeLoc>();
+ if (NestedNameSpecifierLoc QualifierLoc = T.getQualifierLoc())
+ return QualifierLoc.getBeginLoc();
+ return T.getNameLoc();
+ }
+ case TypeLoc::UnresolvedUsing: {
+ auto T = castAs<UnresolvedUsingTypeLoc>();
+ if (NestedNameSpecifierLoc QualifierLoc = T.getQualifierLoc())
+ return QualifierLoc.getBeginLoc();
+ return T.getNameLoc();
+ }
+ case TypeLoc::Using: {
+ auto T = castAs<UsingTypeLoc>();
+ if (NestedNameSpecifierLoc QualifierLoc = T.getQualifierLoc())
+ return QualifierLoc.getBeginLoc();
+ return T.getNameLoc();
+ }
+ default:
+ return getBeginLoc();
+ }
+}
+
void ObjCTypeParamTypeLoc::initializeLocal(ASTContext &Context,
SourceLocation Loc) {
setNameLoc(Loc);
@@ -555,9 +672,9 @@ static void initializeElaboratedKeyword(TL T, SourceLocation Loc) {
: SourceLocation());
}
-static NestedNameSpecifierLoc
-initializeQualifier(ASTContext &Context, NestedNameSpecifier *Qualifier,
- SourceLocation Loc) {
+static NestedNameSpecifierLoc initializeQualifier(ASTContext &Context,
+ NestedNameSpecifier Qualifier,
+ SourceLocation Loc) {
if (!Qualifier)
return NestedNameSpecifierLoc();
NestedNameSpecifierLocBuilder Builder;
@@ -565,15 +682,6 @@ initializeQualifier(ASTContext &Context, NestedNameSpecifier *Qualifier,
return Builder.getWithLocInContext(Context);
}
-void ElaboratedTypeLoc::initializeLocal(ASTContext &Context,
- SourceLocation Loc) {
- if (isEmpty())
- return;
- initializeElaboratedKeyword(*this, Loc);
- setQualifierLoc(
- initializeQualifier(Context, getTypePtr()->getQualifier(), Loc));
-}
-
void DependentNameTypeLoc::initializeLocal(ASTContext &Context,
SourceLocation Loc) {
initializeElaboratedKeyword(*this, Loc);
@@ -596,6 +704,78 @@ DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context,
Context, getTypePtr()->template_arguments(), getArgInfos(), Loc);
}
+void TemplateSpecializationTypeLoc::set(SourceLocation ElaboratedKeywordLoc,
+ NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKeywordLoc,
+ SourceLocation NameLoc,
+ SourceLocation LAngleLoc,
+ SourceLocation RAngleLoc) {
+ TemplateSpecializationLocInfo &Data = *getLocalData();
+
+ Data.ElaboratedKWLoc = ElaboratedKeywordLoc;
+ SourceLocation BeginLoc = ElaboratedKeywordLoc;
+
+ getLocalData()->QualifierData = QualifierLoc.getOpaqueData();
+
+ assert(QualifierLoc.getNestedNameSpecifier() ==
+ getTypePtr()->getTemplateName().getQualifier());
+ Data.QualifierData = QualifierLoc ? QualifierLoc.getOpaqueData() : nullptr;
+ if (QualifierLoc && !BeginLoc.isValid())
+ BeginLoc = QualifierLoc.getBeginLoc();
+
+ Data.TemplateKWLoc = TemplateKeywordLoc;
+ if (!BeginLoc.isValid())
+ BeginLoc = TemplateKeywordLoc;
+
+ Data.NameLoc = NameLoc;
+ if (!BeginLoc.isValid())
+ BeginLoc = NameLoc;
+
+ Data.LAngleLoc = LAngleLoc;
+ Data.SR = SourceRange(BeginLoc, RAngleLoc);
+}
+
+void TemplateSpecializationTypeLoc::set(SourceLocation ElaboratedKeywordLoc,
+ NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKeywordLoc,
+ SourceLocation NameLoc,
+ const TemplateArgumentListInfo &TAL) {
+ set(ElaboratedKeywordLoc, QualifierLoc, TemplateKeywordLoc, NameLoc,
+ TAL.getLAngleLoc(), TAL.getRAngleLoc());
+ MutableArrayRef<TemplateArgumentLocInfo> ArgInfos = getArgLocInfos();
+ assert(TAL.size() == ArgInfos.size());
+ for (unsigned I = 0, N = TAL.size(); I != N; ++I)
+ ArgInfos[I] = TAL[I].getLocInfo();
+}
+
+void TemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context,
+ SourceLocation Loc) {
+ QualifiedTemplateName *Name =
+ getTypePtr()->getTemplateName().getAsAdjustedQualifiedTemplateName();
+
+ SourceLocation ElaboratedKeywordLoc =
+ getTypePtr()->getKeyword() != ElaboratedTypeKeyword::None
+ ? Loc
+ : SourceLocation();
+
+ NestedNameSpecifierLoc QualifierLoc;
+ if (NestedNameSpecifier Qualifier =
+ Name ? Name->getQualifier() : std::nullopt) {
+ NestedNameSpecifierLocBuilder Builder;
+ Builder.MakeTrivial(Context, Qualifier, Loc);
+ QualifierLoc = Builder.getWithLocInContext(Context);
+ }
+
+ TemplateArgumentListInfo TAL(Loc, Loc);
+ set(ElaboratedKeywordLoc, QualifierLoc,
+ /*TemplateKeywordLoc=*/Name && Name->hasTemplateKeyword()
+ ? Loc
+ : SourceLocation(),
+ /*NameLoc=*/Loc, /*LAngleLoc=*/Loc, /*RAngleLoc=*/Loc);
+ initializeArgLocs(Context, getTypePtr()->template_arguments(), getArgInfos(),
+ Loc);
+}
+
void TemplateSpecializationTypeLoc::initializeArgLocs(
ASTContext &Context, ArrayRef<TemplateArgument> Args,
TemplateArgumentLocInfo *ArgInfos, SourceLocation Loc) {
@@ -631,7 +811,7 @@ void TemplateSpecializationTypeLoc::initializeArgLocs(
Builder.MakeTrivial(Context, QTN->getQualifier(), Loc);
ArgInfos[i] = TemplateArgumentLocInfo(
- Context, Builder.getWithLocInContext(Context), Loc,
+ Context, Loc, Builder.getWithLocInContext(Context), Loc,
Args[i].getKind() == TemplateArgument::Template ? SourceLocation()
: Loc);
break;
@@ -680,6 +860,14 @@ void AutoTypeLoc::initializeLocal(ASTContext &Context, SourceLocation Loc) {
}
}
+void DeducedTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context,
+ SourceLocation Loc) {
+ initializeElaboratedKeyword(*this, Loc);
+ setQualifierLoc(initializeQualifier(
+ Context, getTypePtr()->getTemplateName().getQualifier(), Loc));
+ setTemplateNameLoc(Loc);
+}
+
namespace {
class GetContainedAutoTypeLocVisitor :
@@ -693,10 +881,6 @@ namespace {
// Only these types can contain the desired 'auto' type.
- TypeLoc VisitElaboratedTypeLoc(ElaboratedTypeLoc T) {
- return Visit(T.getNamedTypeLoc());
- }
-
TypeLoc VisitQualifiedTypeLoc(QualifiedTypeLoc T) {
return Visit(T.getUnqualifiedLoc());
}
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index deb453f..ce5870e 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -133,7 +133,7 @@ public:
void printAfter(QualType T, raw_ostream &OS);
void AppendScope(DeclContext *DC, raw_ostream &OS,
DeclarationName NameInScope);
- void printTag(TagDecl *T, raw_ostream &OS);
+ void printTagType(const TagType *T, raw_ostream &OS);
void printFunctionAfter(const FunctionType::ExtInfo &Info, raw_ostream &OS);
#define ABSTRACT_TYPE(CLASS, PARENT)
#define TYPE(CLASS, PARENT) \
@@ -230,7 +230,6 @@ bool TypePrinter::canPrefixQualifiers(const Type *T,
case Type::UnaryTransform:
case Type::Record:
case Type::Enum:
- case Type::Elaborated:
case Type::TemplateTypeParm:
case Type::SubstTemplateTypeParmPack:
case Type::DeducedTemplateSpecialization:
@@ -504,11 +503,7 @@ void TypePrinter::printMemberPointerBefore(const MemberPointerType *T,
// FIXME: this should include vectors, but vectors use attributes I guess.
if (isa<ArrayType>(T->getPointeeType()))
OS << '(';
-
- PrintingPolicy InnerPolicy(Policy);
- InnerPolicy.IncludeTagDefinition = false;
- T->getQualifier()->print(OS, InnerPolicy);
-
+ T->getQualifier().print(OS, Policy);
OS << "*";
}
@@ -1211,29 +1206,50 @@ void TypePrinter::printTypeSpec(NamedDecl *D, raw_ostream &OS) {
void TypePrinter::printUnresolvedUsingBefore(const UnresolvedUsingType *T,
raw_ostream &OS) {
- printTypeSpec(T->getDecl(), OS);
+ OS << TypeWithKeyword::getKeywordName(T->getKeyword());
+ if (T->getKeyword() != ElaboratedTypeKeyword::None)
+ OS << ' ';
+ auto *D = T->getDecl();
+ if (Policy.FullyQualifiedName || T->isCanonicalUnqualified()) {
+ AppendScope(D->getDeclContext(), OS, D->getDeclName());
+ } else {
+ T->getQualifier().print(OS, Policy);
+ }
+ OS << D->getIdentifier()->getName();
+ spaceBeforePlaceHolder(OS);
}
void TypePrinter::printUnresolvedUsingAfter(const UnresolvedUsingType *T,
raw_ostream &OS) {}
void TypePrinter::printUsingBefore(const UsingType *T, raw_ostream &OS) {
- // After `namespace b { using a::X }`, is the type X within B a::X or b::X?
- //
- // - b::X is more formally correct given the UsingType model
- // - b::X makes sense if "re-exporting" a symbol in a new namespace
- // - a::X makes sense if "importing" a symbol for convenience
- //
- // The "importing" use seems much more common, so we print a::X.
- // This could be a policy option, but the right choice seems to rest more
- // with the intent of the code than the caller.
- printTypeSpec(T->getFoundDecl()->getUnderlyingDecl(), OS);
+ OS << TypeWithKeyword::getKeywordName(T->getKeyword());
+ if (T->getKeyword() != ElaboratedTypeKeyword::None)
+ OS << ' ';
+ auto *D = T->getDecl();
+ if (Policy.FullyQualifiedName) {
+ AppendScope(D->getDeclContext(), OS, D->getDeclName());
+ } else {
+ T->getQualifier().print(OS, Policy);
+ }
+ OS << D->getIdentifier()->getName();
+ spaceBeforePlaceHolder(OS);
}
void TypePrinter::printUsingAfter(const UsingType *T, raw_ostream &OS) {}
void TypePrinter::printTypedefBefore(const TypedefType *T, raw_ostream &OS) {
- printTypeSpec(T->getDecl(), OS);
+ OS << TypeWithKeyword::getKeywordName(T->getKeyword());
+ if (T->getKeyword() != ElaboratedTypeKeyword::None)
+ OS << ' ';
+ auto *D = T->getDecl();
+ if (Policy.FullyQualifiedName) {
+ AppendScope(D->getDeclContext(), OS, D->getDeclName());
+ } else {
+ T->getQualifier().print(OS, Policy);
+ }
+ OS << D->getIdentifier()->getName();
+ spaceBeforePlaceHolder(OS);
}
void TypePrinter::printMacroQualifiedBefore(const MacroQualifiedType *T,
@@ -1354,14 +1370,53 @@ void TypePrinter::printAutoAfter(const AutoType *T, raw_ostream &OS) {
void TypePrinter::printDeducedTemplateSpecializationBefore(
const DeducedTemplateSpecializationType *T, raw_ostream &OS) {
- // If the type has been deduced, print the deduced type.
+ if (ElaboratedTypeKeyword Keyword = T->getKeyword();
+ T->getKeyword() != ElaboratedTypeKeyword::None)
+ OS << KeywordHelpers::getKeywordName(Keyword) << ' ';
+
+ TemplateName Name = T->getTemplateName();
+
+ // If the type has been deduced, print the template arguments, as if this was
+ // printing the deduced type, but including elaboration and template name
+ // qualification.
+ // FIXME: There should probably be a policy which controls this.
+ // We would probably want to do this on diagnostics, but not on -ast-print.
+ ArrayRef<TemplateArgument> Args;
+ TemplateDecl *DeducedTD = nullptr;
if (!T->getDeducedType().isNull()) {
- printBefore(T->getDeducedType(), OS);
- } else {
+ if (const auto *TST =
+ dyn_cast<TemplateSpecializationType>(T->getDeducedType())) {
+ DeducedTD = TST->getTemplateName().getAsTemplateDecl(
+ /*IgnoreDeduced=*/true);
+ Args = TST->template_arguments();
+ } else {
+ // Should only get here for canonical types.
+ const auto *CD = cast<ClassTemplateSpecializationDecl>(
+ cast<RecordType>(T->getDeducedType())->getOriginalDecl());
+ DeducedTD = CD->getSpecializedTemplate();
+ Args = CD->getTemplateArgs().asArray();
+ }
+
+ // FIXME: Workaround for alias template CTAD not producing guides which
+ // include the alias template specialization type.
+ // Purposefully disregard qualification when building this TemplateName;
+ // any qualification we might have, might not make sense in the
+ // context this was deduced.
+ if (!declaresSameEntity(DeducedTD, Name.getAsTemplateDecl(
+ /*IgnoreDeduced=*/true)))
+ Name = TemplateName(DeducedTD);
+ }
+
+ {
IncludeStrongLifetimeRAII Strong(Policy);
- T->getTemplateName().print(OS, Policy);
- spaceBeforePlaceHolder(OS);
+ Name.print(OS, Policy);
+ }
+ if (DeducedTD) {
+ printTemplateArgumentList(OS, Args, Policy,
+ DeducedTD->getTemplateParameters());
}
+
+ spaceBeforePlaceHolder(OS);
}
void TypePrinter::printDeducedTemplateSpecializationAfter(
@@ -1480,30 +1535,37 @@ void TypePrinter::AppendScope(DeclContext *DC, raw_ostream &OS,
}
}
-void TypePrinter::printTag(TagDecl *D, raw_ostream &OS) {
- if (Policy.IncludeTagDefinition) {
- PrintingPolicy SubPolicy = Policy;
- SubPolicy.IncludeTagDefinition = false;
- D->print(OS, SubPolicy, Indentation);
+void TypePrinter::printTagType(const TagType *T, raw_ostream &OS) {
+ TagDecl *D = T->getOriginalDecl();
+
+ if (Policy.IncludeTagDefinition && T->isTagOwned()) {
+ D->print(OS, Policy, Indentation);
spaceBeforePlaceHolder(OS);
return;
}
bool HasKindDecoration = false;
- // We don't print tags unless this is an elaborated type.
- // In C, we just assume every RecordType is an elaborated type.
- if (!Policy.SuppressTagKeyword && !D->getTypedefNameForAnonDecl()) {
- HasKindDecoration = true;
- OS << D->getKindName();
- OS << ' ';
+ if (T->isCanonicalUnqualified()) {
+ if (!Policy.SuppressTagKeyword && !D->getTypedefNameForAnonDecl()) {
+ HasKindDecoration = true;
+ OS << D->getKindName();
+ OS << ' ';
+ }
+ } else {
+ OS << TypeWithKeyword::getKeywordName(T->getKeyword());
+ if (T->getKeyword() != ElaboratedTypeKeyword::None)
+ OS << ' ';
}
- // Compute the full nested-name-specifier for this type.
- // In C, this will always be empty except when the type
- // being printed is anonymous within other Record.
- if (!Policy.SuppressScope)
+ if (!Policy.FullyQualifiedName && !T->isCanonicalUnqualified()) {
+ T->getQualifier().print(OS, Policy);
+ } else if (!Policy.SuppressScope) {
+ // Compute the full nested-name-specifier for this type.
+ // In C, this will always be empty except when the type
+ // being printed is anonymous within other Record.
AppendScope(D->getDeclContext(), OS, D->getDeclName());
+ }
if (const IdentifierInfo *II = D->getIdentifier())
OS << II->getName();
@@ -1578,9 +1640,11 @@ void TypePrinter::printTag(TagDecl *D, raw_ostream &OS) {
void TypePrinter::printRecordBefore(const RecordType *T, raw_ostream &OS) {
// Print the preferred name if we have one for this type.
if (Policy.UsePreferredNames) {
- for (const auto *PNA : T->getDecl()->specific_attrs<PreferredNameAttr>()) {
+ for (const auto *PNA : T->getOriginalDecl()
+ ->getMostRecentDecl()
+ ->specific_attrs<PreferredNameAttr>()) {
if (!declaresSameEntity(PNA->getTypedefType()->getAsCXXRecordDecl(),
- T->getDecl()))
+ T->getOriginalDecl()))
continue;
// Find the outermost typedef or alias template.
QualType T = PNA->getTypedefType();
@@ -1594,17 +1658,44 @@ void TypePrinter::printRecordBefore(const RecordType *T, raw_ostream &OS) {
}
}
- printTag(T->getDecl(), OS);
+ printTagType(T, OS);
}
void TypePrinter::printRecordAfter(const RecordType *T, raw_ostream &OS) {}
void TypePrinter::printEnumBefore(const EnumType *T, raw_ostream &OS) {
- printTag(T->getDecl(), OS);
+ printTagType(T, OS);
}
void TypePrinter::printEnumAfter(const EnumType *T, raw_ostream &OS) {}
+void TypePrinter::printInjectedClassNameBefore(const InjectedClassNameType *T,
+ raw_ostream &OS) {
+ const ASTContext &Ctx = T->getOriginalDecl()->getASTContext();
+ IncludeStrongLifetimeRAII Strong(Policy);
+ T->getTemplateName(Ctx).print(OS, Policy);
+ if (Policy.PrintInjectedClassNameWithArguments) {
+ auto *Decl = T->getOriginalDecl();
+ // FIXME: Use T->getTemplateArgs(Ctx) when that supports as-written
+ // arguments.
+ if (auto *RD = dyn_cast<ClassTemplateSpecializationDecl>(Decl)) {
+ printTemplateArgumentList(OS, RD->getTemplateArgsAsWritten()->arguments(),
+ Policy,
+ T->getTemplateDecl()->getTemplateParameters());
+ } else {
+ ClassTemplateDecl *TD = Decl->getDescribedClassTemplate();
+ assert(TD);
+ printTemplateArgumentList(
+ OS, TD->getTemplateParameters()->getInjectedTemplateArgs(Ctx), Policy,
+ T->getTemplateDecl()->getTemplateParameters());
+ }
+ }
+ spaceBeforePlaceHolder(OS);
+}
+
+void TypePrinter::printInjectedClassNameAfter(const InjectedClassNameType *T,
+ raw_ostream &OS) {}
+
void TypePrinter::printTemplateTypeParmBefore(const TemplateTypeParmType *T,
raw_ostream &OS) {
TemplateTypeParmDecl *D = T->getDecl();
@@ -1671,6 +1762,10 @@ void TypePrinter::printTemplateId(const TemplateSpecializationType *T,
raw_ostream &OS, bool FullyQualify) {
IncludeStrongLifetimeRAII Strong(Policy);
+ if (ElaboratedTypeKeyword K = T->getKeyword();
+ K != ElaboratedTypeKeyword::None)
+ OS << TypeWithKeyword::getKeywordName(K) << ' ';
+
TemplateDecl *TD =
T->getTemplateName().getAsTemplateDecl(/*IgnoreDeduced=*/true);
// FIXME: Null TD never exercised in test suite.
@@ -1680,7 +1775,10 @@ void TypePrinter::printTemplateId(const TemplateSpecializationType *T,
OS << TD->getName();
} else {
- T->getTemplateName().print(OS, Policy, TemplateName::Qualified::None);
+ T->getTemplateName().print(OS, Policy,
+ !Policy.SuppressScope
+ ? TemplateName::Qualified::AsWritten
+ : TemplateName::Qualified::None);
}
DefaultTemplateArgsPolicyRAII TemplateArgs(Policy);
@@ -1699,77 +1797,6 @@ void TypePrinter::printTemplateSpecializationAfter(
const TemplateSpecializationType *T,
raw_ostream &OS) {}
-void TypePrinter::printInjectedClassNameBefore(const InjectedClassNameType *T,
- raw_ostream &OS) {
- if (Policy.PrintInjectedClassNameWithArguments)
- return printTemplateSpecializationBefore(T->getInjectedTST(), OS);
-
- IncludeStrongLifetimeRAII Strong(Policy);
- T->getTemplateName().print(OS, Policy);
- spaceBeforePlaceHolder(OS);
-}
-
-void TypePrinter::printInjectedClassNameAfter(const InjectedClassNameType *T,
- raw_ostream &OS) {}
-
-void TypePrinter::printElaboratedBefore(const ElaboratedType *T,
- raw_ostream &OS) {
- if (Policy.IncludeTagDefinition && T->getOwnedTagDecl()) {
- TagDecl *OwnedTagDecl = T->getOwnedTagDecl();
- assert(OwnedTagDecl->getTypeForDecl() == T->getNamedType().getTypePtr() &&
- "OwnedTagDecl expected to be a declaration for the type");
- PrintingPolicy SubPolicy = Policy;
- SubPolicy.IncludeTagDefinition = false;
- OwnedTagDecl->print(OS, SubPolicy, Indentation);
- spaceBeforePlaceHolder(OS);
- return;
- }
-
- if (Policy.SuppressElaboration) {
- printBefore(T->getNamedType(), OS);
- return;
- }
-
- // The tag definition will take care of these.
- if (!Policy.IncludeTagDefinition)
- {
- OS << TypeWithKeyword::getKeywordName(T->getKeyword());
- if (T->getKeyword() != ElaboratedTypeKeyword::None)
- OS << " ";
- NestedNameSpecifier *Qualifier = T->getQualifier();
- if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
- !Policy.SuppressUnwrittenScope) {
- bool OldTagKeyword = Policy.SuppressTagKeyword;
- bool OldSupressScope = Policy.SuppressScope;
- Policy.SuppressTagKeyword = true;
- Policy.SuppressScope = false;
- printBefore(T->getNamedType(), OS);
- Policy.SuppressTagKeyword = OldTagKeyword;
- Policy.SuppressScope = OldSupressScope;
- return;
- }
- if (Qualifier)
- Qualifier->print(OS, Policy);
- }
-
- ElaboratedTypePolicyRAII PolicyRAII(Policy);
- printBefore(T->getNamedType(), OS);
-}
-
-void TypePrinter::printElaboratedAfter(const ElaboratedType *T,
- raw_ostream &OS) {
- if (Policy.IncludeTagDefinition && T->getOwnedTagDecl())
- return;
-
- if (Policy.SuppressElaboration) {
- printAfter(T->getNamedType(), OS);
- return;
- }
-
- ElaboratedTypePolicyRAII PolicyRAII(Policy);
- printAfter(T->getNamedType(), OS);
-}
-
void TypePrinter::printParenBefore(const ParenType *T, raw_ostream &OS) {
if (!HasEmptyPlaceHolder && !isa<FunctionType>(T->getInnerType())) {
printBefore(T->getInnerType(), OS);
@@ -1791,9 +1818,7 @@ void TypePrinter::printDependentNameBefore(const DependentNameType *T,
OS << TypeWithKeyword::getKeywordName(T->getKeyword());
if (T->getKeyword() != ElaboratedTypeKeyword::None)
OS << " ";
-
- T->getQualifier()->print(OS, Policy);
-
+ T->getQualifier().print(OS, Policy);
OS << T->getIdentifier()->getName();
spaceBeforePlaceHolder(OS);
}
diff --git a/clang/lib/AST/VTTBuilder.cpp b/clang/lib/AST/VTTBuilder.cpp
index de01184..85101ae 100644
--- a/clang/lib/AST/VTTBuilder.cpp
+++ b/clang/lib/AST/VTTBuilder.cpp
@@ -64,7 +64,9 @@ void VTTBuilder::LayoutSecondaryVTTs(BaseSubobject Base) {
continue;
const auto *BaseDecl =
- cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl());
+ cast<CXXRecordDecl>(
+ I.getType()->castAs<RecordType>()->getOriginalDecl())
+ ->getDefinitionOrSelf();
const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
CharUnits BaseOffset = Base.getBaseOffset() +
@@ -90,7 +92,9 @@ VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base,
for (const auto &I : RD->bases()) {
const auto *BaseDecl =
- cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl());
+ cast<CXXRecordDecl>(
+ I.getType()->castAs<RecordType>()->getOriginalDecl())
+ ->getDefinitionOrSelf();
// Itanium C++ ABI 2.6.2:
// Secondary virtual pointers are present for all bases with either
@@ -154,7 +158,9 @@ void VTTBuilder::LayoutVirtualVTTs(const CXXRecordDecl *RD,
VisitedVirtualBasesSetTy &VBases) {
for (const auto &I : RD->bases()) {
const auto *BaseDecl =
- cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl());
+ cast<CXXRecordDecl>(
+ I.getType()->castAs<RecordType>()->getOriginalDecl())
+ ->getDefinitionOrSelf();
// Check if this is a virtual base.
if (I.isVirtual()) {
diff --git a/clang/lib/AST/VTableBuilder.cpp b/clang/lib/AST/VTableBuilder.cpp
index 0001745..6cec526 100644
--- a/clang/lib/AST/VTableBuilder.cpp
+++ b/clang/lib/AST/VTableBuilder.cpp
@@ -313,10 +313,12 @@ ComputeReturnAdjustmentBaseOffset(ASTContext &Context,
}
const CXXRecordDecl *DerivedRD =
- cast<CXXRecordDecl>(cast<RecordType>(CanDerivedReturnType)->getDecl());
+ cast<CXXRecordDecl>(
+ cast<RecordType>(CanDerivedReturnType)->getOriginalDecl())
+ ->getDefinitionOrSelf();
- const CXXRecordDecl *BaseRD =
- cast<CXXRecordDecl>(cast<RecordType>(CanBaseReturnType)->getDecl());
+ const CXXRecordDecl *BaseRD = cast<CXXRecordDecl>(
+ cast<RecordType>(CanBaseReturnType)->getOriginalDecl());
return ComputeBaseOffset(Context, BaseRD, DerivedRD);
}