[llvm-branch-commits] [clang] [PATCH 2/4] [clang] Improve nested name specifier AST representation (PR #148012)
Matheus Izvekov via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Jul 10 10:53:07 PDT 2025
https://github.com/mizvekov created https://github.com/llvm/llvm-project/pull/148012
Other changes
Second patch in the series starting at https://github.com/llvm/llvm-project/pull/147835
>From 1aae9f78224ae824b58b2f2b450785c080dfffbc Mon Sep 17 00:00:00 2001
From: Matheus Izvekov <mizvekov at gmail.com>
Date: Sat, 12 Apr 2025 23:01:12 -0300
Subject: [PATCH] [PATCH 2/4] [clang] Improve nested name specifier AST
representation
Other changes
---
clang/include/clang/ASTMatchers/ASTMatchers.h | 157 ++---
.../clang/ASTMatchers/ASTMatchersInternal.h | 20 +-
.../clang/Analysis/FlowSensitive/ASTOps.h | 10 +-
clang/include/clang/Basic/DeclNodes.td | 149 +++--
clang/include/clang/Basic/TypeNodes.td | 3 +-
.../clang/ExtractAPI/DeclarationFragments.h | 5 +-
.../include/clang/Sema/CodeCompleteConsumer.h | 7 +-
clang/include/clang/Sema/DeclSpec.h | 48 +-
clang/include/clang/Sema/HeuristicResolver.h | 3 +-
clang/include/clang/Sema/ParsedTemplate.h | 26 +-
clang/include/clang/Sema/Sema.h | 38 +-
clang/include/clang/Sema/SemaInternal.h | 8 +-
clang/include/clang/Sema/TypoCorrection.h | 29 +-
.../clang/Serialization/ASTRecordReader.h | 2 +-
.../clang/Serialization/ASTRecordWriter.h | 5 +-
.../clang/Serialization/TypeBitCodes.def | 1 -
.../clang/Tooling/Refactoring/Lookup.h | 3 +-
.../Refactoring/RecursiveSymbolVisitor.h | 15 +-
clang/lib/ASTMatchers/ASTMatchFinder.cpp | 115 ++--
clang/lib/ASTMatchers/ASTMatchersInternal.cpp | 5 +-
clang/lib/ASTMatchers/Dynamic/Registry.cpp | 5 +-
.../FlowSensitive/DataflowEnvironment.cpp | 6 +-
clang/lib/Analysis/ThreadSafety.cpp | 4 +-
clang/lib/Analysis/ThreadSafetyCommon.cpp | 4 +-
clang/lib/Analysis/UnsafeBufferUsage.cpp | 12 +-
clang/lib/CodeGen/ABIInfo.cpp | 2 +-
clang/lib/CodeGen/ABIInfoImpl.cpp | 36 +-
clang/lib/CodeGen/CGBlocks.cpp | 3 +-
clang/lib/CodeGen/CGCUDANV.cpp | 3 +-
clang/lib/CodeGen/CGCXX.cpp | 19 +-
clang/lib/CodeGen/CGCXXABI.cpp | 4 +-
clang/lib/CodeGen/CGCall.cpp | 27 +-
clang/lib/CodeGen/CGClass.cpp | 95 +--
clang/lib/CodeGen/CGDebugInfo.cpp | 127 ++--
clang/lib/CodeGen/CGDecl.cpp | 13 +-
clang/lib/CodeGen/CGExpr.cpp | 45 +-
clang/lib/CodeGen/CGExprAgg.cpp | 25 +-
clang/lib/CodeGen/CGExprCXX.cpp | 37 +-
clang/lib/CodeGen/CGExprConstant.cpp | 29 +-
clang/lib/CodeGen/CGExprScalar.cpp | 11 +-
clang/lib/CodeGen/CGHLSLRuntime.cpp | 3 +-
clang/lib/CodeGen/CGNonTrivialStruct.cpp | 9 +-
clang/lib/CodeGen/CGObjC.cpp | 4 +-
clang/lib/CodeGen/CGObjCMac.cpp | 11 +-
clang/lib/CodeGen/CGObjCRuntime.cpp | 4 +-
clang/lib/CodeGen/CGOpenMPRuntime.cpp | 35 +-
clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp | 4 +-
clang/lib/CodeGen/CGPointerAuth.cpp | 2 +-
clang/lib/CodeGen/CGStmt.cpp | 4 +-
clang/lib/CodeGen/CGStmtOpenMP.cpp | 9 +-
clang/lib/CodeGen/CGVTables.cpp | 8 +-
clang/lib/CodeGen/CodeGenFunction.cpp | 8 +-
clang/lib/CodeGen/CodeGenFunction.h | 6 +-
clang/lib/CodeGen/CodeGenModule.cpp | 28 +-
clang/lib/CodeGen/CodeGenTBAA.cpp | 13 +-
clang/lib/CodeGen/CodeGenTypes.cpp | 33 +-
clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp | 3 +-
clang/lib/CodeGen/ItaniumCXXABI.cpp | 68 +-
clang/lib/CodeGen/MicrosoftCXXABI.cpp | 25 +-
clang/lib/CodeGen/SwiftCallingConv.cpp | 9 +-
clang/lib/CodeGen/Targets/AArch64.cpp | 9 +-
clang/lib/CodeGen/Targets/AMDGPU.cpp | 6 +-
clang/lib/CodeGen/Targets/ARC.cpp | 5 +-
clang/lib/CodeGen/Targets/ARM.cpp | 9 +-
clang/lib/CodeGen/Targets/BPF.cpp | 5 +-
clang/lib/CodeGen/Targets/CSKY.cpp | 2 +-
clang/lib/CodeGen/Targets/Hexagon.cpp | 5 +-
clang/lib/CodeGen/Targets/Lanai.cpp | 5 +-
clang/lib/CodeGen/Targets/LoongArch.cpp | 10 +-
clang/lib/CodeGen/Targets/Mips.cpp | 8 +-
clang/lib/CodeGen/Targets/NVPTX.cpp | 6 +-
clang/lib/CodeGen/Targets/PNaCl.cpp | 4 +-
clang/lib/CodeGen/Targets/PPC.cpp | 8 +-
clang/lib/CodeGen/Targets/RISCV.cpp | 10 +-
clang/lib/CodeGen/Targets/SPIR.cpp | 6 +-
clang/lib/CodeGen/Targets/Sparc.cpp | 2 +-
clang/lib/CodeGen/Targets/SystemZ.cpp | 8 +-
clang/lib/CodeGen/Targets/WebAssembly.cpp | 3 +-
clang/lib/CodeGen/Targets/X86.cpp | 59 +-
clang/lib/CodeGen/Targets/XCore.cpp | 4 +-
clang/lib/ExtractAPI/DeclarationFragments.cpp | 117 ++--
.../TypedefUnderlyingTypeResolver.cpp | 2 +-
clang/lib/Frontend/ASTConsumers.cpp | 7 +-
clang/lib/Frontend/ASTUnit.cpp | 2 +-
clang/lib/Index/IndexTypeSourceInfo.cpp | 52 +-
clang/lib/Index/USRGeneration.cpp | 18 +-
clang/lib/InstallAPI/Visitor.cpp | 8 +-
.../Interpreter/InterpreterValuePrinter.cpp | 2 +-
clang/lib/Interpreter/Value.cpp | 6 +-
clang/lib/Parse/ParseDeclCXX.cpp | 3 +-
clang/lib/Parse/ParseExprCXX.cpp | 13 +-
clang/lib/Parse/ParseTemplate.cpp | 29 +-
clang/lib/Parse/ParseTentative.cpp | 2 +-
clang/lib/Parse/Parser.cpp | 9 +-
clang/lib/Sema/AnalysisBasedWarnings.cpp | 11 +-
clang/lib/Sema/DeclSpec.cpp | 36 +-
clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp | 23 +-
clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h | 2 +-
clang/lib/Sema/HeuristicResolver.cpp | 50 +-
clang/lib/Sema/Sema.cpp | 21 +-
clang/lib/Sema/SemaAccess.cpp | 43 +-
clang/lib/Sema/SemaAvailability.cpp | 4 +-
clang/lib/Sema/SemaBPF.cpp | 6 +-
clang/lib/Sema/SemaCUDA.cpp | 7 +-
clang/lib/Sema/SemaCXXScopeSpec.cpp | 331 +++++-----
clang/lib/Sema/SemaCast.cpp | 51 +-
clang/lib/Sema/SemaChecking.cpp | 97 +--
clang/lib/Sema/SemaCodeComplete.cpp | 181 +++---
clang/lib/Sema/SemaCoroutine.cpp | 35 +-
clang/lib/Sema/SemaDecl.cpp | 591 ++++++++++--------
clang/lib/Sema/SemaDeclAttr.cpp | 23 +-
clang/lib/Sema/SemaDeclCXX.cpp | 484 +++++++-------
clang/lib/Sema/SemaDeclObjC.cpp | 32 +-
clang/lib/Sema/SemaExceptionSpec.cpp | 5 +-
clang/lib/Sema/SemaExpr.cpp | 125 ++--
clang/lib/Sema/SemaExprCXX.cpp | 162 ++---
clang/lib/Sema/SemaExprMember.cpp | 7 +-
clang/lib/Sema/SemaExprObjC.cpp | 15 +-
clang/lib/Sema/SemaFunctionEffects.cpp | 8 +-
clang/lib/Sema/SemaHLSL.cpp | 20 +-
clang/lib/Sema/SemaInit.cpp | 145 +++--
clang/lib/Sema/SemaLambda.cpp | 8 +-
clang/lib/Sema/SemaLookup.cpp | 240 ++++---
clang/lib/Sema/SemaObjC.cpp | 5 +-
clang/lib/Sema/SemaObjCProperty.cpp | 4 +-
clang/lib/Sema/SemaOpenMP.cpp | 13 +-
clang/lib/Sema/SemaOverload.cpp | 181 +++---
clang/lib/Sema/SemaPPC.cpp | 6 +-
clang/lib/Sema/SemaSYCL.cpp | 2 +-
clang/lib/Sema/SemaStmt.cpp | 40 +-
clang/lib/Sema/SemaStmtAsm.cpp | 10 +-
clang/lib/Sema/SemaSwift.cpp | 5 +-
clang/lib/Sema/SemaTemplate.cpp | 544 ++++++++--------
clang/lib/Sema/SemaTemplateDeduction.cpp | 162 +++--
clang/lib/Sema/SemaTemplateDeductionGuide.cpp | 58 +-
clang/lib/Sema/SemaTemplateInstantiate.cpp | 184 +++---
.../lib/Sema/SemaTemplateInstantiateDecl.cpp | 84 ++-
clang/lib/Sema/SemaTemplateVariadic.cpp | 39 +-
clang/lib/Sema/SemaType.cpp | 184 +++---
clang/lib/Sema/SemaTypeTraits.cpp | 35 +-
clang/lib/Sema/UsedDeclVisitor.h | 7 +-
clang/lib/Serialization/ASTReader.cpp | 126 ++--
clang/lib/Serialization/ASTReaderDecl.cpp | 28 +-
clang/lib/Serialization/ASTWriter.cpp | 113 ++--
clang/lib/Serialization/ASTWriterDecl.cpp | 7 +-
.../Serialization/TemplateArgumentHasher.cpp | 8 +-
.../Checkers/CallAndMessageChecker.cpp | 2 +-
.../Checkers/CastSizeChecker.cpp | 2 +-
.../Checkers/DynamicTypePropagation.cpp | 2 +-
.../Checkers/EnumCastOutOfRangeChecker.cpp | 3 +-
.../Checkers/LLVMConventionsChecker.cpp | 7 +-
.../Checkers/NonNullParamChecker.cpp | 4 +-
.../NonnullGlobalConstantsChecker.cpp | 5 +-
.../NumberObjectConversionChecker.cpp | 11 +-
.../Checkers/PaddingChecker.cpp | 16 +-
.../Checkers/StdLibraryFunctionsChecker.cpp | 4 +-
.../Checkers/WebKit/PtrTypesSemantics.cpp | 33 +-
.../WebKit/RefCntblBaseVirtualDtorChecker.cpp | 8 +-
clang/lib/StaticAnalyzer/Core/CallEvent.cpp | 11 +-
clang/lib/StaticAnalyzer/Core/MemRegion.cpp | 4 +-
clang/lib/StaticAnalyzer/Core/RegionStore.cpp | 5 +-
clang/lib/StaticAnalyzer/Core/SValBuilder.cpp | 4 +-
clang/lib/Tooling/ASTDiff/ASTDiff.cpp | 13 +-
clang/lib/Tooling/Refactoring/Lookup.cpp | 14 +-
.../Refactoring/Rename/USRLocFinder.cpp | 167 ++---
clang/lib/Tooling/Syntax/BuildTree.cpp | 172 +++--
.../lib/Tooling/Transformer/RangeSelector.cpp | 8 +-
clang/tools/libclang/CIndex.cpp | 179 ++----
clang/tools/libclang/CIndexCodeCompletion.cpp | 4 +-
clang/tools/libclang/CXCursor.cpp | 8 +-
clang/tools/libclang/CXIndexDataConsumer.cpp | 25 +-
clang/tools/libclang/CXType.cpp | 36 +-
clang/tools/libclang/CursorVisitor.h | 4 +-
173 files changed, 3741 insertions(+), 3504 deletions(-)
diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h
index bae004896c11f..599155c5c9950 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -221,6 +221,19 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, TypedefNameDecl>
extern const internal::VariadicDynCastAllOfMatcher<Decl, TypeAliasDecl>
typeAliasDecl;
+/// \brief Matches shadow declarations introduced into a scope by a
+/// (resolved) using declaration.
+///
+/// Given
+/// \code
+/// namespace n { int f; }
+/// namespace declToImport { using n::f; }
+/// \endcode
+/// usingShadowDecl()
+/// matches \code f \endcode
+extern const internal::VariadicDynCastAllOfMatcher<Decl, UsingShadowDecl>
+ usingShadowDecl;
+
/// Matches type alias template declarations.
///
/// typeAliasTemplateDecl() matches
@@ -3718,7 +3731,7 @@ extern const internal::VariadicOperatorMatcherFunc<1, 1> unless;
/// Matcher<MemberExpr>, Matcher<QualType>, Matcher<RecordType>,
/// Matcher<TagType>, Matcher<TemplateSpecializationType>,
/// Matcher<TemplateTypeParmType>, Matcher<TypedefType>,
-/// Matcher<UnresolvedUsingType>
+/// Matcher<UnresolvedUsingType>, Matcher<UsingType>
inline internal::PolymorphicMatcher<
internal::HasDeclarationMatcher,
void(internal::HasDeclarationSupportedTypes), internal::Matcher<Decl>>
@@ -4353,7 +4366,13 @@ AST_POLYMORPHIC_MATCHER_P(throughUsingDecl,
AST_POLYMORPHIC_SUPPORTED_TYPES(DeclRefExpr,
UsingType),
internal::Matcher<UsingShadowDecl>, Inner) {
- const NamedDecl *FoundDecl = Node.getFoundDecl();
+ const NamedDecl *FoundDecl;
+ if constexpr (std::is_same_v<NodeType, UsingType>) {
+ FoundDecl = Node.getDecl();
+ } else {
+ static_assert(std::is_same_v<NodeType, DeclRefExpr>);
+ FoundDecl = Node.getFoundDecl();
+ }
if (const UsingShadowDecl *UsingDecl = dyn_cast<UsingShadowDecl>(FoundDecl))
return Inner.matches(*UsingDecl, Finder, Builder);
return false;
@@ -6982,37 +7001,6 @@ AST_POLYMORPHIC_MATCHER_P2(
InnerMatcher.matches(Args[Index], Finder, Builder);
}
-/// Matches C or C++ elaborated `TypeLoc`s.
-///
-/// Given
-/// \code
-/// struct s {};
-/// struct s ss;
-/// \endcode
-/// elaboratedTypeLoc()
-/// matches the `TypeLoc` of the variable declaration of `ss`.
-extern const internal::VariadicDynCastAllOfMatcher<TypeLoc, ElaboratedTypeLoc>
- elaboratedTypeLoc;
-
-/// Matches elaborated `TypeLoc`s that have a named `TypeLoc` matching
-/// `InnerMatcher`.
-///
-/// Given
-/// \code
-/// template <typename T>
-/// class C {};
-/// class C<int> c;
-///
-/// class D {};
-/// class D d;
-/// \endcode
-/// elaboratedTypeLoc(hasNamedTypeLoc(templateSpecializationTypeLoc()));
-/// matches the `TypeLoc` of the variable declaration of `c`, but not `d`.
-AST_MATCHER_P(ElaboratedTypeLoc, hasNamedTypeLoc, internal::Matcher<TypeLoc>,
- InnerMatcher) {
- return InnerMatcher.matches(Node.getNamedTypeLoc(), Finder, Builder);
-}
-
/// Matches type \c bool.
///
/// Given
@@ -7279,7 +7267,7 @@ extern const AstTypeMatcher<DecltypeType> decltypeType;
AST_TYPE_TRAVERSE_MATCHER(hasDeducedType, getDeducedType,
AST_POLYMORPHIC_SUPPORTED_TYPES(AutoType));
-/// Matches \c DecltypeType or \c UsingType nodes to find the underlying type.
+/// Matches \c QualType nodes to find the underlying type.
///
/// Given
/// \code
@@ -7289,10 +7277,13 @@ AST_TYPE_TRAVERSE_MATCHER(hasDeducedType, getDeducedType,
/// decltypeType(hasUnderlyingType(isInteger()))
/// matches the type of "a"
///
-/// Usable as: Matcher<DecltypeType>, Matcher<UsingType>
-AST_TYPE_TRAVERSE_MATCHER(hasUnderlyingType, getUnderlyingType,
- AST_POLYMORPHIC_SUPPORTED_TYPES(DecltypeType,
- UsingType));
+/// Usable as: Matcher<QualType>
+AST_MATCHER_P(Type, hasUnderlyingType, internal::Matcher<QualType>, Inner) {
+ QualType QT = Node.getLocallyUnqualifiedSingleStepDesugaredType();
+ if (QT == QualType(&Node, 0))
+ return false;
+ return Inner.matches(QT, Finder, Builder);
+}
/// Matches \c FunctionType nodes.
///
@@ -7571,27 +7562,7 @@ extern const AstTypeMatcher<RecordType> recordType;
/// and \c c.
extern const AstTypeMatcher<TagType> tagType;
-/// Matches types specified with an elaborated type keyword or with a
-/// qualified name.
-///
-/// Given
-/// \code
-/// namespace N {
-/// namespace M {
-/// class D {};
-/// }
-/// }
-/// class C {};
-///
-/// class C c;
-/// N::M::D d;
-/// \endcode
-///
-/// \c elaboratedType() matches the type of the variable declarations of both
-/// \c c and \c d.
-extern const AstTypeMatcher<ElaboratedType> elaboratedType;
-
-/// Matches ElaboratedTypes whose qualifier, a NestedNameSpecifier,
+/// Matches Types whose qualifier, a NestedNameSpecifier,
/// matches \c InnerMatcher if the qualifier exists.
///
/// Given
@@ -7606,34 +7577,14 @@ extern const AstTypeMatcher<ElaboratedType> elaboratedType;
///
/// \c elaboratedType(hasQualifier(hasPrefix(specifiesNamespace(hasName("N"))))
/// matches the type of the variable declaration of \c d.
-AST_MATCHER_P(ElaboratedType, hasQualifier,
- internal::Matcher<NestedNameSpecifier>, InnerMatcher) {
- if (const NestedNameSpecifier *Qualifier = Node.getQualifier())
- return InnerMatcher.matches(*Qualifier, Finder, Builder);
+AST_MATCHER_P(Type, hasQualifier, internal::Matcher<NestedNameSpecifier>,
+ InnerMatcher) {
+ if (NestedNameSpecifier Qualifier = Node.getPrefix())
+ return InnerMatcher.matches(Qualifier, Finder, Builder);
return false;
}
-/// Matches ElaboratedTypes whose named type matches \c InnerMatcher.
-///
-/// Given
-/// \code
-/// namespace N {
-/// namespace M {
-/// class D {};
-/// }
-/// }
-/// N::M::D d;
-/// \endcode
-///
-/// \c elaboratedType(namesType(recordType(
-/// hasDeclaration(namedDecl(hasName("D")))))) matches the type of the variable
-/// declaration of \c d.
-AST_MATCHER_P(ElaboratedType, namesType, internal::Matcher<QualType>,
- InnerMatcher) {
- return InnerMatcher.matches(Node.getNamedType(), Finder, Builder);
-}
-
/// Matches types specified through a using declaration.
///
/// Given
@@ -7802,7 +7753,7 @@ AST_MATCHER_FUNCTION_P_OVERLOAD(
/// matches "A::"
AST_MATCHER_P(NestedNameSpecifier, specifiesType,
internal::Matcher<QualType>, InnerMatcher) {
- if (!Node.getAsType())
+ if (Node.getKind() != NestedNameSpecifier::Kind::Type)
return false;
return InnerMatcher.matches(QualType(Node.getAsType(), 0), Finder, Builder);
}
@@ -7820,8 +7771,12 @@ AST_MATCHER_P(NestedNameSpecifier, specifiesType,
/// matches "A::"
AST_MATCHER_P(NestedNameSpecifierLoc, specifiesTypeLoc,
internal::Matcher<TypeLoc>, InnerMatcher) {
- return Node && Node.getNestedNameSpecifier()->getAsType() &&
- InnerMatcher.matches(Node.getTypeLoc(), Finder, Builder);
+ if (!Node)
+ return false;
+ TypeLoc TL = Node.getAsTypeLoc();
+ if (!TL)
+ return false;
+ return InnerMatcher.matches(TL, Finder, Builder);
}
/// Matches on the prefix of a \c NestedNameSpecifier.
@@ -7836,10 +7791,21 @@ AST_MATCHER_P(NestedNameSpecifierLoc, specifiesTypeLoc,
AST_MATCHER_P_OVERLOAD(NestedNameSpecifier, hasPrefix,
internal::Matcher<NestedNameSpecifier>, InnerMatcher,
0) {
- const NestedNameSpecifier *NextNode = Node.getPrefix();
+ NestedNameSpecifier NextNode = std::nullopt;
+ switch (Node.getKind()) {
+ case NestedNameSpecifier::Kind::Namespace:
+ NextNode = Node.getAsNamespaceAndPrefix().Prefix;
+ break;
+ case NestedNameSpecifier::Kind::Type:
+ NextNode = Node.getAsType()->getPrefix();
+ break;
+ default:
+ break;
+ }
+
if (!NextNode)
return false;
- return InnerMatcher.matches(*NextNode, Finder, Builder);
+ return InnerMatcher.matches(NextNode, Finder, Builder);
}
/// Matches on the prefix of a \c NestedNameSpecifierLoc.
@@ -7854,7 +7820,12 @@ AST_MATCHER_P_OVERLOAD(NestedNameSpecifier, hasPrefix,
AST_MATCHER_P_OVERLOAD(NestedNameSpecifierLoc, hasPrefix,
internal::Matcher<NestedNameSpecifierLoc>, InnerMatcher,
1) {
- NestedNameSpecifierLoc NextNode = Node.getPrefix();
+ NestedNameSpecifierLoc NextNode;
+ if (TypeLoc TL = Node.getAsTypeLoc())
+ NextNode = TL.getPrefix();
+ else
+ NextNode = Node.getAsNamespaceAndPrefix().Prefix;
+
if (!NextNode)
return false;
return InnerMatcher.matches(NextNode, Finder, Builder);
@@ -7872,9 +7843,13 @@ AST_MATCHER_P_OVERLOAD(NestedNameSpecifierLoc, hasPrefix,
/// matches "ns::"
AST_MATCHER_P(NestedNameSpecifier, specifiesNamespace,
internal::Matcher<NamespaceDecl>, InnerMatcher) {
- if (!Node.getAsNamespace())
+ if (Node.getKind() != NestedNameSpecifier::Kind::Namespace)
+ return false;
+ const auto *Namespace =
+ dyn_cast<NamespaceDecl>(Node.getAsNamespaceAndPrefix().Namespace);
+ if (!Namespace)
return false;
- return InnerMatcher.matches(*Node.getAsNamespace(), Finder, Builder);
+ return InnerMatcher.matches(*Namespace, Finder, Builder);
}
/// Matches attributes.
diff --git a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
index 667a044abcef1..399af3d888551 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -1013,10 +1013,7 @@ class HasDeclarationMatcher : public MatcherInterface<T> {
// First, for any types that have a declaration, extract the declaration and
// match on it.
if (const auto *S = dyn_cast<TagType>(&Node)) {
- return matchesDecl(S->getDecl(), Finder, Builder);
- }
- if (const auto *S = dyn_cast<InjectedClassNameType>(&Node)) {
- return matchesDecl(S->getDecl(), Finder, Builder);
+ return matchesDecl(S->getOriginalDecl(), Finder, Builder);
}
if (const auto *S = dyn_cast<TemplateTypeParmType>(&Node)) {
return matchesDecl(S->getDecl(), Finder, Builder);
@@ -1027,6 +1024,9 @@ class HasDeclarationMatcher : public MatcherInterface<T> {
if (const auto *S = dyn_cast<UnresolvedUsingType>(&Node)) {
return matchesDecl(S->getDecl(), Finder, Builder);
}
+ if (const auto *S = dyn_cast<UsingType>(&Node)) {
+ return matchesDecl(S->getDecl(), Finder, Builder);
+ }
if (const auto *S = dyn_cast<ObjCObjectType>(&Node)) {
return matchesDecl(S->getInterface(), Finder, Builder);
}
@@ -1062,12 +1062,6 @@ class HasDeclarationMatcher : public MatcherInterface<T> {
Builder);
}
- // FIXME: We desugar elaborated types. This makes the assumption that users
- // do never want to match on whether a type is elaborated - there are
- // arguments for both sides; for now, continue desugaring.
- if (const auto *S = dyn_cast<ElaboratedType>(&Node)) {
- return matchesSpecialized(S->desugar(), Finder, Builder);
- }
// Similarly types found via using declarations.
// These are *usually* meaningless sugar, and this matches the historical
// behavior prior to the introduction of UsingType.
@@ -1207,8 +1201,8 @@ using AdaptativeDefaultToTypes =
/// All types that are supported by HasDeclarationMatcher above.
using HasDeclarationSupportedTypes =
TypeList<CallExpr, CXXConstructExpr, CXXNewExpr, DeclRefExpr, EnumType,
- ElaboratedType, InjectedClassNameType, LabelStmt, AddrLabelExpr,
- MemberExpr, QualType, RecordType, TagType,
+ InjectedClassNameType, LabelStmt, AddrLabelExpr, MemberExpr,
+ QualType, RecordType, TagType, UsingType,
TemplateSpecializationType, TemplateTypeParmType, TypedefType,
UnresolvedUsingType, ObjCIvarRefExpr, ObjCInterfaceDecl>;
@@ -1785,7 +1779,7 @@ class LocMatcher : public MatcherInterface<TLoc> {
private:
static DynTypedNode extract(const NestedNameSpecifierLoc &Loc) {
- return DynTypedNode::create(*Loc.getNestedNameSpecifier());
+ return DynTypedNode::create(Loc.getNestedNameSpecifier());
}
};
diff --git a/clang/include/clang/Analysis/FlowSensitive/ASTOps.h b/clang/include/clang/Analysis/FlowSensitive/ASTOps.h
index 8c7ee86d15c06..a404b06cd62ca 100644
--- a/clang/include/clang/Analysis/FlowSensitive/ASTOps.h
+++ b/clang/include/clang/Analysis/FlowSensitive/ASTOps.h
@@ -112,8 +112,14 @@ class AnalysisASTVisitor : public DynamicRecursiveASTVisitor {
// fields that are only used in these.
// Note: The operand of the `noexcept` operator is an unevaluated operand, but
// nevertheless it appears in the Clang CFG, so we don't exclude it here.
- bool TraverseDecltypeTypeLoc(DecltypeTypeLoc) override { return true; }
- bool TraverseTypeOfExprTypeLoc(TypeOfExprTypeLoc) override { return true; }
+ bool TraverseDecltypeTypeLoc(DecltypeTypeLoc,
+ bool TraverseQualifier) override {
+ return true;
+ }
+ bool TraverseTypeOfExprTypeLoc(TypeOfExprTypeLoc,
+ bool TraverseQualifier) override {
+ return true;
+ }
bool TraverseCXXTypeidExpr(CXXTypeidExpr *TIE) override {
if (TIE->isPotentiallyEvaluated())
return DynamicRecursiveASTVisitor::TraverseCXXTypeidExpr(TIE);
diff --git a/clang/include/clang/Basic/DeclNodes.td b/clang/include/clang/Basic/DeclNodes.td
index f1ebaf1db3fc0..b4c02949426a1 100644
--- a/clang/include/clang/Basic/DeclNodes.td
+++ b/clang/include/clang/Basic/DeclNodes.td
@@ -15,81 +15,80 @@ def PragmaComment : DeclNode<Decl>;
def PragmaDetectMismatch : DeclNode<Decl>;
def ExternCContext : DeclNode<Decl>, DeclContext;
def Named : DeclNode<Decl, "named declarations", 1>;
- def Namespace : DeclNode<Named, "namespaces">, DeclContext;
- def UsingDirective : DeclNode<Named>;
- def NamespaceAlias : DeclNode<Named>;
- def Label : DeclNode<Named, "labels">;
- def Type : DeclNode<Named, "types", 1>;
- def TypedefName : DeclNode<Type, "typedefs", 1>;
- def Typedef : DeclNode<TypedefName>;
- def TypeAlias : DeclNode<TypedefName>;
- def ObjCTypeParam : DeclNode<TypedefName>;
- def UnresolvedUsingTypename : DeclNode<Type>;
- def Tag : DeclNode<Type, "tag types", 1>, DeclContext;
- def Enum : DeclNode<Tag, "enums">;
- def Record : DeclNode<Tag, "structs, unions, classes">;
- def CXXRecord : DeclNode<Record, "classes">;
- def ClassTemplateSpecialization : DeclNode<CXXRecord>;
- def ClassTemplatePartialSpecialization
- : DeclNode<ClassTemplateSpecialization>;
- def TemplateTypeParm : DeclNode<Type>;
- def Value : DeclNode<Named, "value declarations", 1>;
- def EnumConstant : DeclNode<Value, "enumerators">;
- def UnresolvedUsingValue : DeclNode<Value>;
- def IndirectField : DeclNode<Value>;
- def Binding : DeclNode<Value>;
- def OMPDeclareReduction : DeclNode<Value>, DeclContext;
- def OMPDeclareMapper : DeclNode<Value>, DeclContext;
- def MSGuid : DeclNode<Value>;
- def UnnamedGlobalConstant : DeclNode<Value>;
- def TemplateParamObject : DeclNode<Value>;
- def Declarator : DeclNode<Value, "declarators", 1>;
- def Field : DeclNode<Declarator, "non-static data members">;
- def ObjCIvar : DeclNode<Field>;
- def ObjCAtDefsField : DeclNode<Field>;
- def MSProperty : DeclNode<Declarator>;
- def Function : DeclNode<Declarator, "functions">, DeclContext;
- def CXXDeductionGuide : DeclNode<Function>;
- def CXXMethod : DeclNode<Function>;
- def CXXConstructor : DeclNode<CXXMethod>;
- def CXXDestructor : DeclNode<CXXMethod>;
- def CXXConversion : DeclNode<CXXMethod>;
- def Var : DeclNode<Declarator, "variables">;
- def VarTemplateSpecialization : DeclNode<Var>;
- def VarTemplatePartialSpecialization
- : DeclNode<VarTemplateSpecialization>;
- def ImplicitParam : DeclNode<Var>;
- def ParmVar : DeclNode<Var, "parameters">;
- def Decomposition : DeclNode<Var>;
- def OMPCapturedExpr : DeclNode<Var>;
- def NonTypeTemplateParm : DeclNode<Declarator>;
- def Template : DeclNode<Named, "templates", 1>;
- def RedeclarableTemplate : DeclNode<Template, "redeclarable templates", 1>;
- def FunctionTemplate : DeclNode<RedeclarableTemplate>;
- def ClassTemplate : DeclNode<RedeclarableTemplate>;
- def VarTemplate : DeclNode<RedeclarableTemplate>;
- def TypeAliasTemplate : DeclNode<RedeclarableTemplate>;
- def TemplateTemplateParm : DeclNode<Template>;
- def BuiltinTemplate : DeclNode<Template>;
- def Concept : DeclNode<Template>;
- def BaseUsing : DeclNode<Named, "", 1>;
- def Using : DeclNode<BaseUsing>;
- def UsingEnum : DeclNode<BaseUsing>;
- def UsingPack : DeclNode<Named>;
- def UsingShadow : DeclNode<Named>;
- def ConstructorUsingShadow : DeclNode<UsingShadow>;
- def UnresolvedUsingIfExists : DeclNode<Named>;
- def ObjCMethod : DeclNode<Named, "Objective-C methods">, DeclContext;
- def ObjCContainer : DeclNode<Named, "Objective-C containers", 1>, DeclContext;
- def ObjCCategory : DeclNode<ObjCContainer>;
- def ObjCProtocol : DeclNode<ObjCContainer, "Objective-C protocols">;
- def ObjCInterface : DeclNode<ObjCContainer, "Objective-C interfaces">;
- def ObjCImpl
- : DeclNode<ObjCContainer, "Objective-C implementation declarations", 1>;
- def ObjCCategoryImpl : DeclNode<ObjCImpl>;
- def ObjCImplementation : DeclNode<ObjCImpl>;
- def ObjCProperty : DeclNode<Named, "Objective-C properties">;
- def ObjCCompatibleAlias : DeclNode<Named>;
+def NamespaceBase : DeclNode<Named, "namespace declarations", 1>;
+def Namespace : DeclNode<NamespaceBase, "namespaces">, DeclContext;
+def NamespaceAlias : DeclNode<NamespaceBase>;
+def UsingDirective : DeclNode<Named>;
+def Label : DeclNode<Named, "labels">;
+def Type : DeclNode<Named, "types", 1>;
+def TypedefName : DeclNode<Type, "typedefs", 1>;
+def Typedef : DeclNode<TypedefName>;
+def TypeAlias : DeclNode<TypedefName>;
+def ObjCTypeParam : DeclNode<TypedefName>;
+def UnresolvedUsingTypename : DeclNode<Type>;
+def Tag : DeclNode<Type, "tag types", 1>, DeclContext;
+def Enum : DeclNode<Tag, "enums">;
+def Record : DeclNode<Tag, "structs, unions, classes">;
+def CXXRecord : DeclNode<Record, "classes">;
+def ClassTemplateSpecialization : DeclNode<CXXRecord>;
+def ClassTemplatePartialSpecialization : DeclNode<ClassTemplateSpecialization>;
+def TemplateTypeParm : DeclNode<Type>;
+def Value : DeclNode<Named, "value declarations", 1>;
+def EnumConstant : DeclNode<Value, "enumerators">;
+def UnresolvedUsingValue : DeclNode<Value>;
+def IndirectField : DeclNode<Value>;
+def Binding : DeclNode<Value>;
+def OMPDeclareReduction : DeclNode<Value>, DeclContext;
+def OMPDeclareMapper : DeclNode<Value>, DeclContext;
+def MSGuid : DeclNode<Value>;
+def UnnamedGlobalConstant : DeclNode<Value>;
+def TemplateParamObject : DeclNode<Value>;
+def Declarator : DeclNode<Value, "declarators", 1>;
+def Field : DeclNode<Declarator, "non-static data members">;
+def ObjCIvar : DeclNode<Field>;
+def ObjCAtDefsField : DeclNode<Field>;
+def MSProperty : DeclNode<Declarator>;
+def Function : DeclNode<Declarator, "functions">, DeclContext;
+def CXXDeductionGuide : DeclNode<Function>;
+def CXXMethod : DeclNode<Function>;
+def CXXConstructor : DeclNode<CXXMethod>;
+def CXXDestructor : DeclNode<CXXMethod>;
+def CXXConversion : DeclNode<CXXMethod>;
+def Var : DeclNode<Declarator, "variables">;
+def VarTemplateSpecialization : DeclNode<Var>;
+def VarTemplatePartialSpecialization : DeclNode<VarTemplateSpecialization>;
+def ImplicitParam : DeclNode<Var>;
+def ParmVar : DeclNode<Var, "parameters">;
+def Decomposition : DeclNode<Var>;
+def OMPCapturedExpr : DeclNode<Var>;
+def NonTypeTemplateParm : DeclNode<Declarator>;
+def Template : DeclNode<Named, "templates", 1>;
+def RedeclarableTemplate : DeclNode<Template, "redeclarable templates", 1>;
+def FunctionTemplate : DeclNode<RedeclarableTemplate>;
+def ClassTemplate : DeclNode<RedeclarableTemplate>;
+def VarTemplate : DeclNode<RedeclarableTemplate>;
+def TypeAliasTemplate : DeclNode<RedeclarableTemplate>;
+def TemplateTemplateParm : DeclNode<Template>;
+def BuiltinTemplate : DeclNode<Template>;
+def Concept : DeclNode<Template>;
+def BaseUsing : DeclNode<Named, "", 1>;
+def Using : DeclNode<BaseUsing>;
+def UsingEnum : DeclNode<BaseUsing>;
+def UsingPack : DeclNode<Named>;
+def UsingShadow : DeclNode<Named>;
+def ConstructorUsingShadow : DeclNode<UsingShadow>;
+def UnresolvedUsingIfExists : DeclNode<Named>;
+def ObjCMethod : DeclNode<Named, "Objective-C methods">, DeclContext;
+def ObjCContainer : DeclNode<Named, "Objective-C containers", 1>, DeclContext;
+def ObjCCategory : DeclNode<ObjCContainer>;
+def ObjCProtocol : DeclNode<ObjCContainer, "Objective-C protocols">;
+def ObjCInterface : DeclNode<ObjCContainer, "Objective-C interfaces">;
+def ObjCImpl
+ : DeclNode<ObjCContainer, "Objective-C implementation declarations", 1>;
+def ObjCCategoryImpl : DeclNode<ObjCImpl>;
+def ObjCImplementation : DeclNode<ObjCImpl>;
+def ObjCProperty : DeclNode<Named, "Objective-C properties">;
+def ObjCCompatibleAlias : DeclNode<Named>;
def ImplicitConceptSpecialization : DeclNode<Decl>;
def LinkageSpec : DeclNode<Decl>, DeclContext;
def Export : DeclNode<Decl>, DeclContext;
diff --git a/clang/include/clang/Basic/TypeNodes.td b/clang/include/clang/Basic/TypeNodes.td
index 567b8a5ca5a4d..5f3b20e4f3245 100644
--- a/clang/include/clang/Basic/TypeNodes.td
+++ b/clang/include/clang/Basic/TypeNodes.td
@@ -90,7 +90,7 @@ def UnaryTransformType : TypeNode<Type>, NeverCanonicalUnlessDependent;
def TagType : TypeNode<Type, 1>;
def RecordType : TypeNode<TagType>, LeafType;
def EnumType : TypeNode<TagType>, LeafType;
-def ElaboratedType : TypeNode<Type>, NeverCanonical;
+def InjectedClassNameType : TypeNode<TagType>, AlwaysDependent, LeafType;
def AttributedType : TypeNode<Type>, NeverCanonical;
def BTFTagAttributedType : TypeNode<Type>, NeverCanonical;
def HLSLAttributedResourceType : TypeNode<Type>;
@@ -102,7 +102,6 @@ def TemplateSpecializationType : TypeNode<Type>, NeverCanonicalUnlessDependent;
def DeducedType : TypeNode<Type, 1>;
def AutoType : TypeNode<DeducedType>;
def DeducedTemplateSpecializationType : TypeNode<DeducedType>;
-def InjectedClassNameType : TypeNode<Type>, AlwaysDependent, LeafType;
def DependentNameType : TypeNode<Type>, AlwaysDependent;
def DependentTemplateSpecializationType : TypeNode<Type>, AlwaysDependent;
def PackExpansionType : TypeNode<Type>, AlwaysDependent;
diff --git a/clang/include/clang/ExtractAPI/DeclarationFragments.h b/clang/include/clang/ExtractAPI/DeclarationFragments.h
index 4ac744459031e..4859225ef4ced 100644
--- a/clang/include/clang/ExtractAPI/DeclarationFragments.h
+++ b/clang/include/clang/ExtractAPI/DeclarationFragments.h
@@ -440,9 +440,8 @@ class DeclarationFragmentsBuilder {
DeclarationFragments &);
/// Build DeclarationFragments for a NestedNameSpecifier.
- static DeclarationFragments getFragmentsForNNS(const NestedNameSpecifier *,
- ASTContext &,
- DeclarationFragments &);
+ static DeclarationFragments
+ getFragmentsForNNS(NestedNameSpecifier, ASTContext &, DeclarationFragments &);
/// Build DeclarationFragments for Qualifiers.
static DeclarationFragments getFragmentsForQualifiers(const Qualifiers quals);
diff --git a/clang/include/clang/Sema/CodeCompleteConsumer.h b/clang/include/clang/Sema/CodeCompleteConsumer.h
index 2dd27593778c7..c26f4e33d289c 100644
--- a/clang/include/clang/Sema/CodeCompleteConsumer.h
+++ b/clang/include/clang/Sema/CodeCompleteConsumer.h
@@ -162,7 +162,8 @@ SimplifiedTypeClass getSimplifiedTypeClass(CanQualType T);
/// Determine the type that this declaration will have if it is used
/// as a type or in an expression.
-QualType getDeclUsageType(ASTContext &C, const NamedDecl *ND);
+QualType getDeclUsageType(ASTContext &C, NestedNameSpecifier Qualifier,
+ const NamedDecl *ND);
/// Determine the priority to be given to a macro code completion result
/// with the given name.
@@ -867,7 +868,7 @@ class CodeCompletionResult {
/// If the result should have a nested-name-specifier, this is it.
/// When \c QualifierIsInformative, the nested-name-specifier is
/// informative rather than required.
- NestedNameSpecifier *Qualifier = nullptr;
+ NestedNameSpecifier Qualifier = std::nullopt;
/// If this Decl was unshadowed by using declaration, this can store a
/// pointer to the UsingShadowDecl which was used in the unshadowing process.
@@ -882,7 +883,7 @@ class CodeCompletionResult {
/// Build a result that refers to a declaration.
CodeCompletionResult(const NamedDecl *Declaration, unsigned Priority,
- NestedNameSpecifier *Qualifier = nullptr,
+ NestedNameSpecifier Qualifier = std::nullopt,
bool QualifierIsInformative = false,
bool Accessible = true,
std::vector<FixItHint> FixIts = std::vector<FixItHint>())
diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h
index 567ad2d5934d4..f16d9b5680ee2 100644
--- a/clang/include/clang/Sema/DeclSpec.h
+++ b/clang/include/clang/Sema/DeclSpec.h
@@ -92,12 +92,11 @@ class CXXScopeSpec {
}
/// Retrieve the representation of the nested-name-specifier.
- NestedNameSpecifier *getScopeRep() const {
+ NestedNameSpecifier getScopeRep() const {
return Builder.getRepresentation();
}
- /// Extend the current nested-name-specifier by another
- /// nested-name-specifier component of the form 'type::'.
+ /// Make a nested-name-specifier of the form 'type::'.
///
/// \param Context The AST context in which this nested-name-specifier
/// resides.
@@ -107,21 +106,7 @@ class CXXScopeSpec {
/// \param TL The TypeLoc that describes the type preceding the '::'.
///
/// \param ColonColonLoc The location of the trailing '::'.
- void Extend(ASTContext &Context, TypeLoc TL, SourceLocation ColonColonLoc);
-
- /// Extend the current nested-name-specifier by another
- /// nested-name-specifier component of the form 'identifier::'.
- ///
- /// \param Context The AST context in which this nested-name-specifier
- /// resides.
- ///
- /// \param Identifier The identifier.
- ///
- /// \param IdentifierLoc The location of the identifier.
- ///
- /// \param ColonColonLoc The location of the trailing '::'.
- void Extend(ASTContext &Context, IdentifierInfo *Identifier,
- SourceLocation IdentifierLoc, SourceLocation ColonColonLoc);
+ void Make(ASTContext &Context, TypeLoc TL, SourceLocation ColonColonLoc);
/// Extend the current nested-name-specifier by another
/// nested-name-specifier component of the form 'namespace::'.
@@ -134,24 +119,9 @@ class CXXScopeSpec {
/// \param NamespaceLoc The location of the namespace name.
///
/// \param ColonColonLoc The location of the trailing '::'.
- void Extend(ASTContext &Context, NamespaceDecl *Namespace,
+ void Extend(ASTContext &Context, NamespaceBaseDecl *Namespace,
SourceLocation NamespaceLoc, SourceLocation ColonColonLoc);
- /// Extend the current nested-name-specifier by another
- /// nested-name-specifier component of the form 'namespace-alias::'.
- ///
- /// \param Context The AST context in which this nested-name-specifier
- /// resides.
- ///
- /// \param Alias The namespace alias.
- ///
- /// \param AliasLoc The location of the namespace alias
- /// name.
- ///
- /// \param ColonColonLoc The location of the trailing '::'.
- void Extend(ASTContext &Context, NamespaceAliasDecl *Alias,
- SourceLocation AliasLoc, SourceLocation ColonColonLoc);
-
/// Turn this (empty) nested-name-specifier into the global
/// nested-name-specifier '::'.
void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc);
@@ -178,7 +148,7 @@ class CXXScopeSpec {
/// FIXME: This routine should be used very, very rarely, in cases where we
/// need to synthesize a nested-name-specifier. Most code should instead use
/// \c Adopt() with a proper \c NestedNameSpecifierLoc.
- void MakeTrivial(ASTContext &Context, NestedNameSpecifier *Qualifier,
+ void MakeTrivial(ASTContext &Context, NestedNameSpecifier Qualifier,
SourceRange R);
/// Adopt an existing nested-name-specifier (with source-range
@@ -204,14 +174,14 @@ class CXXScopeSpec {
SourceLocation getLastQualifierNameLoc() const;
/// No scope specifier.
- bool isEmpty() const { return Range.isInvalid() && getScopeRep() == nullptr; }
+ bool isEmpty() const { return Range.isInvalid() && !getScopeRep(); }
/// A scope specifier is present, but may be valid or invalid.
bool isNotEmpty() const { return !isEmpty(); }
/// An error occurred during parsing of the scope specifier.
- bool isInvalid() const { return Range.isValid() && getScopeRep() == nullptr; }
+ bool isInvalid() const { return Range.isValid() && !getScopeRep(); }
/// A scope specifier is present, and it refers to a real scope.
- bool isValid() const { return getScopeRep() != nullptr; }
+ bool isValid() const { return bool(getScopeRep()); }
/// Indicate that this nested-name-specifier is invalid.
void SetInvalid(SourceRange R) {
@@ -224,7 +194,7 @@ class CXXScopeSpec {
/// Deprecated. Some call sites intend isNotEmpty() while others intend
/// isValid().
- bool isSet() const { return getScopeRep() != nullptr; }
+ bool isSet() const { return bool(getScopeRep()); }
void clear() {
Range = SourceRange();
diff --git a/clang/include/clang/Sema/HeuristicResolver.h b/clang/include/clang/Sema/HeuristicResolver.h
index e193c0bc14cd9..71588bee92d16 100644
--- a/clang/include/clang/Sema/HeuristicResolver.h
+++ b/clang/include/clang/Sema/HeuristicResolver.h
@@ -67,8 +67,7 @@ class HeuristicResolver {
// Try to heuristically resolve a dependent nested name specifier
// to the type it likely denotes. Note that *dependent* name specifiers always
// denote types, not namespaces.
- QualType
- resolveNestedNameSpecifierToType(const NestedNameSpecifier *NNS) const;
+ QualType resolveNestedNameSpecifierToType(NestedNameSpecifier NNS) const;
// Perform an imprecise lookup of a dependent name in `RD`.
// This function does not follow strict semantic rules and should be used
diff --git a/clang/include/clang/Sema/ParsedTemplate.h b/clang/include/clang/Sema/ParsedTemplate.h
index 3a8050f9a0a3d..4a3df781b5a58 100644
--- a/clang/include/clang/Sema/ParsedTemplate.h
+++ b/clang/include/clang/Sema/ParsedTemplate.h
@@ -48,8 +48,8 @@ namespace clang {
///
/// \param Arg the template type argument or non-type template argument.
/// \param Loc the location of the type.
- ParsedTemplateArgument(KindType Kind, void *Arg, SourceLocation Loc)
- : Kind(Kind), Arg(Arg), Loc(Loc) { }
+ ParsedTemplateArgument(KindType Kind, void *Arg, SourceLocation NameLoc)
+ : Kind(Kind), Arg(Arg), NameLoc(NameLoc) {}
/// Create a template template argument.
///
@@ -60,11 +60,11 @@ namespace clang {
/// argument refers.
///
/// \param TemplateLoc the location of the template name.
- ParsedTemplateArgument(const CXXScopeSpec &SS,
- ParsedTemplateTy Template,
- SourceLocation TemplateLoc)
- : Kind(ParsedTemplateArgument::Template),
- Arg(Template.getAsOpaquePtr()), SS(SS), Loc(TemplateLoc) {}
+ ParsedTemplateArgument(SourceLocation TemplateKwLoc, const CXXScopeSpec &SS,
+ ParsedTemplateTy Template, SourceLocation NameLoc)
+ : Kind(ParsedTemplateArgument::Template),
+ Arg(Template.getAsOpaquePtr()), SS(SS), TemplateKwLoc(TemplateKwLoc),
+ NameLoc(NameLoc) {}
/// Determine whether the given template argument is invalid.
bool isInvalid() const { return Arg == nullptr; }
@@ -91,7 +91,10 @@ namespace clang {
}
/// Retrieve the location of the template argument.
- SourceLocation getLocation() const { return Loc; }
+ SourceLocation getTemplateKwLoc() const { return TemplateKwLoc; }
+
+ /// Retrieve the location of the template argument.
+ SourceLocation getNameLoc() const { return NameLoc; }
/// Retrieve the nested-name-specifier that precedes the template
/// name in a template template argument.
@@ -128,8 +131,11 @@ namespace clang {
/// argument.
CXXScopeSpec SS;
- /// the location of the template argument.
- SourceLocation Loc;
+ /// the location of the template keyword.
+ SourceLocation TemplateKwLoc;
+
+ /// the location of the template name.
+ SourceLocation NameLoc;
/// The ellipsis location that can accompany a template template
/// argument (turning it into a template template argument expansion).
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index b281b1cfef96a..c6319672ef823 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -3208,7 +3208,7 @@ class Sema final : public SemaBase {
/// current instantiation (C++0x [temp.dep.type]p1).
///
/// \param NNS a dependent nested name specifier.
- CXXRecordDecl *getCurrentInstantiationOf(NestedNameSpecifier *NNS);
+ CXXRecordDecl *getCurrentInstantiationOf(NestedNameSpecifier NNS);
/// The parser has parsed a global nested-name-specifier '::'.
///
@@ -3245,7 +3245,7 @@ class Sema final : public SemaBase {
/// (e.g., Base::), perform name lookup for that identifier as a
/// nested-name-specifier within the given scope, and return the result of
/// that name lookup.
- NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS);
+ NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier NNS);
/// Keeps information about an identifier in a nested-name-spec.
///
@@ -3564,8 +3564,8 @@ class Sema final : public SemaBase {
/// Returns the TypeDeclType for the given type declaration,
/// as ASTContext::getTypeDeclType would, but
/// performs the required semantic checks for name lookup of said entity.
- QualType getTypeDeclType(DeclContext *LookupCtx, DiagCtorKind DCK,
- TypeDecl *TD, SourceLocation NameLoc);
+ void checkTypeDeclType(DeclContext *LookupCtx, DiagCtorKind DCK, TypeDecl *TD,
+ SourceLocation NameLoc);
/// If the identifier refers to a type name within this scope,
/// return the declaration of that type.
@@ -7607,7 +7607,7 @@ class Sema final : public SemaBase {
/// "real" base class is checked as appropriate when checking the access of
/// the member name.
ExprResult PerformObjectMemberConversion(Expr *From,
- NestedNameSpecifier *Qualifier,
+ NestedNameSpecifier Qualifier,
NamedDecl *FoundDecl,
NamedDecl *Member);
@@ -10185,7 +10185,7 @@ class Sema final : public SemaBase {
ExprResult InitializeExplicitObjectArgument(Sema &S, Expr *Obj,
FunctionDecl *Fun);
ExprResult PerformImplicitObjectArgumentInitialization(
- Expr *From, NestedNameSpecifier *Qualifier, NamedDecl *FoundDecl,
+ Expr *From, NestedNameSpecifier Qualifier, NamedDecl *FoundDecl,
CXXMethodDecl *Method);
/// PerformContextuallyConvertToBool - Perform a contextual conversion
@@ -11592,13 +11592,16 @@ class Sema final : public SemaBase {
void NoteAllFoundTemplates(TemplateName Name);
- QualType CheckTemplateIdType(TemplateName Template,
+ QualType CheckTemplateIdType(ElaboratedTypeKeyword Keyword,
+ TemplateName Template,
SourceLocation TemplateLoc,
TemplateArgumentListInfo &TemplateArgs);
TypeResult
- ActOnTemplateIdType(Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
- TemplateTy Template, const IdentifierInfo *TemplateII,
+ ActOnTemplateIdType(Scope *S, ElaboratedTypeKeyword ElaboratedKeyword,
+ SourceLocation ElaboratedKeywordLoc, CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc, TemplateTy Template,
+ const IdentifierInfo *TemplateII,
SourceLocation TemplateIILoc, SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgs, SourceLocation RAngleLoc,
bool IsCtorOrDtorName = false, bool IsClassName = false,
@@ -11827,8 +11830,8 @@ class Sema final : public SemaBase {
/// argument, substitute into that default template argument and
/// return the corresponding template argument.
TemplateArgumentLoc SubstDefaultTemplateArgumentIfAvailable(
- TemplateDecl *Template, SourceLocation TemplateLoc,
- SourceLocation RAngleLoc, Decl *Param,
+ TemplateDecl *Template, SourceLocation TemplateKWLoc,
+ SourceLocation TemplateNameLoc, SourceLocation RAngleLoc, Decl *Param,
ArrayRef<TemplateArgument> SugaredConverted,
ArrayRef<TemplateArgument> CanonicalConverted, bool &HasDefaultArg);
@@ -13738,8 +13741,9 @@ class Sema final : public SemaBase {
SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo,
const MultiLevelTemplateArgumentList &TemplateArgs);
TemplateName
- SubstTemplateName(NestedNameSpecifierLoc QualifierLoc, TemplateName Name,
- SourceLocation Loc,
+ SubstTemplateName(SourceLocation TemplateKWLoc,
+ NestedNameSpecifierLoc &QualifierLoc, TemplateName Name,
+ SourceLocation NameLoc,
const MultiLevelTemplateArgumentList &TemplateArgs);
bool SubstTypeConstraint(TemplateTypeParmDecl *Inst, const TypeConstraint *TC,
@@ -15155,14 +15159,6 @@ class Sema final : public SemaBase {
return RequireCompleteExprType(E, CompleteTypeKind::Default, Diagnoser);
}
- /// Retrieve a version of the type 'T' that is elaborated by Keyword,
- /// qualified by the nested-name-specifier contained in SS, and that is
- /// (re)declared by OwnedTagDecl, which is nullptr if this is not a
- /// (re)declaration.
- QualType getElaboratedType(ElaboratedTypeKeyword Keyword,
- const CXXScopeSpec &SS, QualType T,
- TagDecl *OwnedTagDecl = nullptr);
-
// Returns the underlying type of a decltype with the given expression.
QualType getDecltypeForExpr(Expr *E);
diff --git a/clang/include/clang/Sema/SemaInternal.h b/clang/include/clang/Sema/SemaInternal.h
index 4d0da1102bb59..c6287f4c76a11 100644
--- a/clang/include/clang/Sema/SemaInternal.h
+++ b/clang/include/clang/Sema/SemaInternal.h
@@ -208,7 +208,7 @@ class TypoCorrectionConsumer : public VisibleDeclConsumer {
class NamespaceSpecifierSet {
struct SpecifierInfo {
DeclContext* DeclCtx;
- NestedNameSpecifier* NameSpecifier;
+ NestedNameSpecifier NameSpecifier;
unsigned EditDistance;
};
@@ -228,9 +228,9 @@ class TypoCorrectionConsumer : public VisibleDeclConsumer {
static DeclContextList buildContextChain(DeclContext *Start);
unsigned buildNestedNameSpecifier(DeclContextList &DeclChain,
- NestedNameSpecifier *&NNS);
+ NestedNameSpecifier &NNS);
- public:
+ public:
NamespaceSpecifierSet(ASTContext &Context, DeclContext *CurContext,
CXXScopeSpec *CurScopeSpec);
@@ -275,7 +275,7 @@ class TypoCorrectionConsumer : public VisibleDeclConsumer {
};
void addName(StringRef Name, NamedDecl *ND,
- NestedNameSpecifier *NNS = nullptr, bool isKeyword = false);
+ NestedNameSpecifier NNS = std::nullopt, bool isKeyword = false);
/// Find any visible decls for the given typo correction candidate.
/// If none are found, it to the set of candidates for which qualified lookups
diff --git a/clang/include/clang/Sema/TypoCorrection.h b/clang/include/clang/Sema/TypoCorrection.h
index 09de164297e7b..1d780c45efd55 100644
--- a/clang/include/clang/Sema/TypoCorrection.h
+++ b/clang/include/clang/Sema/TypoCorrection.h
@@ -57,15 +57,15 @@ class TypoCorrection {
static const unsigned CallbackDistanceWeight = 150U;
TypoCorrection(const DeclarationName &Name, NamedDecl *NameDecl,
- NestedNameSpecifier *NNS = nullptr, unsigned CharDistance = 0,
- unsigned QualifierDistance = 0)
+ NestedNameSpecifier NNS = std::nullopt,
+ unsigned CharDistance = 0, unsigned QualifierDistance = 0)
: CorrectionName(Name), CorrectionNameSpec(NNS),
CharDistance(CharDistance), QualifierDistance(QualifierDistance) {
if (NameDecl)
CorrectionDecls.push_back(NameDecl);
}
- TypoCorrection(NamedDecl *Name, NestedNameSpecifier *NNS = nullptr,
+ TypoCorrection(NamedDecl *Name, NestedNameSpecifier NNS = std::nullopt,
unsigned CharDistance = 0)
: CorrectionName(Name->getDeclName()), CorrectionNameSpec(NNS),
CharDistance(CharDistance) {
@@ -73,7 +73,7 @@ class TypoCorrection {
CorrectionDecls.push_back(Name);
}
- TypoCorrection(DeclarationName Name, NestedNameSpecifier *NNS = nullptr,
+ TypoCorrection(DeclarationName Name, NestedNameSpecifier NNS = std::nullopt,
unsigned CharDistance = 0)
: CorrectionName(Name), CorrectionNameSpec(NNS),
CharDistance(CharDistance) {}
@@ -88,13 +88,13 @@ class TypoCorrection {
}
/// Gets the NestedNameSpecifier needed to use the typo correction
- NestedNameSpecifier *getCorrectionSpecifier() const {
+ NestedNameSpecifier getCorrectionSpecifier() const {
return CorrectionNameSpec;
}
- void setCorrectionSpecifier(NestedNameSpecifier *NNS) {
+ void setCorrectionSpecifier(NestedNameSpecifier NNS) {
CorrectionNameSpec = NNS;
- ForceSpecifierReplacement = (NNS != nullptr);
+ ForceSpecifierReplacement = !!NNS;
}
void WillReplaceSpecifier(bool ForceReplacement) {
@@ -264,7 +264,7 @@ class TypoCorrection {
// Results.
DeclarationName CorrectionName;
- NestedNameSpecifier *CorrectionNameSpec = nullptr;
+ NestedNameSpecifier CorrectionNameSpec = std::nullopt;
SmallVector<NamedDecl *, 1> CorrectionDecls;
unsigned CharDistance = 0;
unsigned QualifierDistance = 0;
@@ -282,8 +282,9 @@ class CorrectionCandidateCallback {
public:
static const unsigned InvalidDistance = TypoCorrection::InvalidDistance;
- explicit CorrectionCandidateCallback(const IdentifierInfo *Typo = nullptr,
- NestedNameSpecifier *TypoNNS = nullptr)
+ explicit CorrectionCandidateCallback(
+ const IdentifierInfo *Typo = nullptr,
+ NestedNameSpecifier TypoNNS = std::nullopt)
: Typo(Typo), TypoNNS(TypoNNS) {}
virtual ~CorrectionCandidateCallback() = default;
@@ -320,7 +321,7 @@ class CorrectionCandidateCallback {
virtual std::unique_ptr<CorrectionCandidateCallback> clone() = 0;
void setTypoName(const IdentifierInfo *II) { Typo = II; }
- void setTypoNNS(NestedNameSpecifier *NNS) { TypoNNS = NNS; }
+ void setTypoNNS(NestedNameSpecifier NNS) { TypoNNS = NNS; }
// Flags for context-dependent keywords. WantFunctionLikeCasts is only
// used/meaningful when WantCXXNamedCasts is false.
@@ -346,13 +347,13 @@ class CorrectionCandidateCallback {
}
const IdentifierInfo *Typo;
- NestedNameSpecifier *TypoNNS;
+ NestedNameSpecifier TypoNNS;
};
class DefaultFilterCCC final : public CorrectionCandidateCallback {
public:
explicit DefaultFilterCCC(const IdentifierInfo *Typo = nullptr,
- NestedNameSpecifier *TypoNNS = nullptr)
+ NestedNameSpecifier TypoNNS = std::nullopt)
: CorrectionCandidateCallback(Typo, TypoNNS) {}
std::unique_ptr<CorrectionCandidateCallback> clone() override {
@@ -366,7 +367,7 @@ template <class C>
class DeclFilterCCC final : public CorrectionCandidateCallback {
public:
explicit DeclFilterCCC(const IdentifierInfo *Typo = nullptr,
- NestedNameSpecifier *TypoNNS = nullptr)
+ NestedNameSpecifier TypoNNS = std::nullopt)
: CorrectionCandidateCallback(Typo, TypoNNS) {}
bool ValidateCandidate(const TypoCorrection &candidate) override {
diff --git a/clang/include/clang/Serialization/ASTRecordReader.h b/clang/include/clang/Serialization/ASTRecordReader.h
index 1472497ff5e7e..aed1b7d309001 100644
--- a/clang/include/clang/Serialization/ASTRecordReader.h
+++ b/clang/include/clang/Serialization/ASTRecordReader.h
@@ -223,7 +223,7 @@ class ASTRecordReader
void readQualifierInfo(QualifierInfo &Info);
/// Return a nested name specifier, advancing Idx.
- // NestedNameSpecifier *readNestedNameSpecifier(); (inherited)
+ // NestedNameSpecifier readNestedNameSpecifier(); (inherited)
NestedNameSpecifierLoc readNestedNameSpecifierLoc();
diff --git a/clang/include/clang/Serialization/ASTRecordWriter.h b/clang/include/clang/Serialization/ASTRecordWriter.h
index ee005ec287708..9849ea6b395ab 100644
--- a/clang/include/clang/Serialization/ASTRecordWriter.h
+++ b/clang/include/clang/Serialization/ASTRecordWriter.h
@@ -247,8 +247,7 @@ class ASTRecordWriter
void AddTypeLoc(TypeLoc TL);
/// Emits a template argument location info.
- void AddTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,
- const TemplateArgumentLocInfo &Arg);
+ void AddTemplateArgumentLocInfo(const TemplateArgumentLoc &Arg);
/// Emits a template argument location.
void AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg);
@@ -280,7 +279,7 @@ class ASTRecordWriter
void AddQualifierInfo(const QualifierInfo &Info);
/// Emit a nested name specifier.
- void AddNestedNameSpecifier(NestedNameSpecifier *NNS) {
+ void AddNestedNameSpecifier(NestedNameSpecifier NNS) {
writeNestedNameSpecifier(NNS);
}
diff --git a/clang/include/clang/Serialization/TypeBitCodes.def b/clang/include/clang/Serialization/TypeBitCodes.def
index b8cde2e370960..8abdf5e842541 100644
--- a/clang/include/clang/Serialization/TypeBitCodes.def
+++ b/clang/include/clang/Serialization/TypeBitCodes.def
@@ -32,7 +32,6 @@ TYPE_BIT_CODE(Enum, ENUM, 20)
TYPE_BIT_CODE(ObjCInterface, OBJC_INTERFACE, 21)
TYPE_BIT_CODE(ObjCObjectPointer, OBJC_OBJECT_POINTER, 22)
TYPE_BIT_CODE(Decltype, DECLTYPE, 23)
-TYPE_BIT_CODE(Elaborated, ELABORATED, 24)
TYPE_BIT_CODE(SubstTemplateTypeParm, SUBST_TEMPLATE_TYPE_PARM, 25)
TYPE_BIT_CODE(UnresolvedUsing, UNRESOLVED_USING, 26)
TYPE_BIT_CODE(InjectedClassName, INJECTED_CLASS_NAME, 27)
diff --git a/clang/include/clang/Tooling/Refactoring/Lookup.h b/clang/include/clang/Tooling/Refactoring/Lookup.h
index dcb40b7eee66c..fe0df8656bce1 100644
--- a/clang/include/clang/Tooling/Refactoring/Lookup.h
+++ b/clang/include/clang/Tooling/Refactoring/Lookup.h
@@ -38,8 +38,7 @@ namespace tooling {
/// \param ReplacementString The replacement nested name. Must be fully
/// qualified including a leading "::".
/// \returns The new name to be inserted in place of the current nested name.
-std::string replaceNestedName(const NestedNameSpecifier *Use,
- SourceLocation UseLoc,
+std::string replaceNestedName(NestedNameSpecifier Use, SourceLocation UseLoc,
const DeclContext *UseContext,
const NamedDecl *FromDecl,
StringRef ReplacementString);
diff --git a/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h b/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h
index 015dbba26f688..319569fd5ab33 100644
--- a/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h
+++ b/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h
@@ -108,18 +108,21 @@ class RecursiveSymbolVisitor
bool VisitTypedefTypeLoc(TypedefTypeLoc TL) {
const SourceLocation TypeEndLoc =
Lexer::getLocForEndOfToken(TL.getBeginLoc(), 0, SM, LangOpts);
- return visit(TL.getTypedefNameDecl(), TL.getBeginLoc(), TypeEndLoc);
+ return visit(TL.getDecl(), TL.getBeginLoc(), TypeEndLoc);
}
- bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
+ bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc QualifierLoc) {
// The base visitor will visit NNSL prefixes, so we should only look at
// the current NNS.
- if (NNS) {
- const NamespaceDecl *ND = NNS.getNestedNameSpecifier()->getAsNamespace();
- if (!visit(ND, NNS.getLocalBeginLoc(), NNS.getLocalEndLoc()))
+ if (NestedNameSpecifier Qualifier = QualifierLoc.getNestedNameSpecifier();
+ Qualifier.getKind() == NestedNameSpecifier::Kind::Namespace) {
+ const auto *ND = dyn_cast<NamespaceDecl>(
+ Qualifier.getAsNamespaceAndPrefix().Namespace);
+ if (!visit(ND, QualifierLoc.getLocalBeginLoc(),
+ QualifierLoc.getLocalEndLoc()))
return false;
}
- return BaseType::TraverseNestedNameSpecifierLoc(NNS);
+ return BaseType::TraverseNestedNameSpecifierLoc(QualifierLoc);
}
bool VisitDesignatedInitExpr(const DesignatedInitExpr *E) {
diff --git a/clang/lib/ASTMatchers/ASTMatchFinder.cpp b/clang/lib/ASTMatchers/ASTMatchFinder.cpp
index 6d0ba0b7907a1..d43d1aec71b29 100644
--- a/clang/lib/ASTMatchers/ASTMatchFinder.cpp
+++ b/clang/lib/ASTMatchers/ASTMatchFinder.cpp
@@ -122,15 +122,15 @@ class MatchChildASTVisitor
else if (const Stmt *S = DynNode.get<Stmt>())
traverse(*S);
else if (const NestedNameSpecifier *NNS =
- DynNode.get<NestedNameSpecifier>())
+ DynNode.get<NestedNameSpecifier>())
traverse(*NNS);
else if (const NestedNameSpecifierLoc *NNSLoc =
DynNode.get<NestedNameSpecifierLoc>())
traverse(*NNSLoc);
else if (const QualType *Q = DynNode.get<QualType>())
- traverse(*Q);
+ traverse(*Q, /*TraverseQualifier=*/true);
else if (const TypeLoc *T = DynNode.get<TypeLoc>())
- traverse(*T);
+ traverse(*T, /*TraverseQualifier=*/true);
else if (const auto *C = DynNode.get<CXXCtorInitializer>())
traverse(*C);
else if (const TemplateArgumentLoc *TALoc =
@@ -194,7 +194,7 @@ class MatchChildASTVisitor
}
// We assume that the QualType and the contained type are on the same
// hierarchy level. Thus, we try to match either of them.
- bool TraverseType(QualType TypeNode) {
+ bool TraverseType(QualType TypeNode, bool TraverseQualifier = true) {
if (TypeNode.isNull())
return true;
ScopedIncrement ScopedDepth(&CurrentDepth);
@@ -202,11 +202,11 @@ class MatchChildASTVisitor
if (!match(*TypeNode))
return false;
// The QualType is matched inside traverse.
- return traverse(TypeNode);
+ return traverse(TypeNode, TraverseQualifier);
}
// We assume that the TypeLoc, contained QualType and contained Type all are
// on the same hierarchy level. Thus, we try to match all of them.
- bool TraverseTypeLoc(TypeLoc TypeLocNode) {
+ bool TraverseTypeLoc(TypeLoc TypeLocNode, bool TraverseQualifier = true) {
if (TypeLocNode.isNull())
return true;
ScopedIncrement ScopedDepth(&CurrentDepth);
@@ -217,17 +217,17 @@ class MatchChildASTVisitor
if (!match(TypeLocNode.getType()))
return false;
// The TypeLoc is matched inside traverse.
- return traverse(TypeLocNode);
+ return traverse(TypeLocNode, TraverseQualifier);
}
- bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) {
+ bool TraverseNestedNameSpecifier(NestedNameSpecifier NNS) {
ScopedIncrement ScopedDepth(&CurrentDepth);
- return (NNS == nullptr) || traverse(*NNS);
+ return !NNS || traverse(NNS);
}
bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
if (!NNS)
return true;
ScopedIncrement ScopedDepth(&CurrentDepth);
- if (!match(*NNS.getNestedNameSpecifier()))
+ if (!match(NNS.getNestedNameSpecifier()))
return false;
return traverse(NNS);
}
@@ -340,15 +340,14 @@ class MatchChildASTVisitor
bool baseTraverse(const Stmt &StmtNode) {
return VisitorBase::TraverseStmt(const_cast<Stmt*>(&StmtNode));
}
- bool baseTraverse(QualType TypeNode) {
- return VisitorBase::TraverseType(TypeNode);
+ bool baseTraverse(QualType TypeNode, bool TraverseQualifier) {
+ return VisitorBase::TraverseType(TypeNode, TraverseQualifier);
}
- bool baseTraverse(TypeLoc TypeLocNode) {
- return VisitorBase::TraverseTypeLoc(TypeLocNode);
+ bool baseTraverse(TypeLoc TypeLocNode, bool TraverseQualifier) {
+ return VisitorBase::TraverseTypeLoc(TypeLocNode, TraverseQualifier);
}
- bool baseTraverse(const NestedNameSpecifier &NNS) {
- return VisitorBase::TraverseNestedNameSpecifier(
- const_cast<NestedNameSpecifier*>(&NNS));
+ bool baseTraverse(NestedNameSpecifier NNS) {
+ return VisitorBase::TraverseNestedNameSpecifier(NNS);
}
bool baseTraverse(NestedNameSpecifierLoc NNS) {
return VisitorBase::TraverseNestedNameSpecifierLoc(NNS);
@@ -396,13 +395,13 @@ class MatchChildASTVisitor
// Traverses the subtree rooted at 'Node'; returns true if the
// traversal should continue after this function returns.
- template <typename T>
- bool traverse(const T &Node) {
+ template <typename T, class... Args>
+ bool traverse(const T &Node, Args &&...args) {
static_assert(IsBaseType<T>::value,
"traverse can only be instantiated with base type");
if (!match(Node))
return false;
- return baseTraverse(Node);
+ return baseTraverse(Node, std::forward<Args>(args)...);
}
const DynTypedMatcher *const Matcher;
@@ -501,9 +500,9 @@ class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
bool TraverseDecl(Decl *DeclNode);
bool TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue = nullptr);
- bool TraverseType(QualType TypeNode);
- bool TraverseTypeLoc(TypeLoc TypeNode);
- bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS);
+ bool TraverseType(QualType TypeNode, bool TraverseQualifier = true);
+ bool TraverseTypeLoc(TypeLoc TypeNode, bool TraverseQualifier = true);
+ bool TraverseNestedNameSpecifier(NestedNameSpecifier NNS);
bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
bool TraverseConstructorInitializer(CXXCtorInitializer *CtorInit);
bool TraverseTemplateArgumentLoc(TemplateArgumentLoc TAL);
@@ -577,13 +576,13 @@ class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
const auto *T = Proto.getTypePtr();
for (const auto &E : T->exceptions())
- TraverseType(E);
+ TraverseType(E, /*TraverseQualifier=*/true);
if (Expr *NE = T->getNoexceptExpr())
TraverseStmt(NE, Queue);
if (LE->hasExplicitResultType())
- TraverseTypeLoc(Proto.getReturnLoc());
+ TraverseTypeLoc(Proto.getReturnLoc(), /*TraverseQualifier=*/true);
TraverseStmt(
const_cast<Expr *>(LE->getTrailingRequiresClause().ConstraintExpr));
}
@@ -1289,33 +1288,42 @@ class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
if (Aliases == TypeAliases.end())
return false;
- if (const auto *ElaboratedTypeNode =
- llvm::dyn_cast<ElaboratedType>(TypeNode)) {
- if (ElaboratedTypeNode->isSugared() && Aliases->second.size() > 1) {
- const auto &DesugaredTypeName =
- ElaboratedTypeNode->desugar().getAsString();
+ auto matches = [&](const TypedefNameDecl *Alias) {
+ BoundNodesTreeBuilder Result(*Builder);
+ if (Matcher.matches(*Alias, this, &Result)) {
+ *Builder = std::move(Result);
+ return true;
+ }
+ return false;
+ };
- for (const TypedefNameDecl *Alias : Aliases->second) {
- if (Alias->getName() != DesugaredTypeName) {
- continue;
- }
+ if (const auto *T = TypeNode->getAs<TypedefType>()) {
+ const auto *TD = T->getDecl()->getCanonicalDecl();
- BoundNodesTreeBuilder Result(*Builder);
- if (Matcher.matches(*Alias, this, &Result)) {
- *Builder = std::move(Result);
- return true;
- }
+ // Prioritize exact matches.
+ SmallVector<const TypedefNameDecl *, 8> NonExactMatches;
+ for (const TypedefNameDecl *Alias : Aliases->second) {
+ if (!declaresSameEntity(TD, Alias)) {
+ NonExactMatches.push_back(Alias);
+ continue;
}
+ if (matches(Alias))
+ return true;
}
- }
- for (const TypedefNameDecl *Alias : Aliases->second) {
- BoundNodesTreeBuilder Result(*Builder);
- if (Matcher.matches(*Alias, this, &Result)) {
- *Builder = std::move(Result);
- return true;
+ for (const TypedefNameDecl *Alias : NonExactMatches) {
+ BoundNodesTreeBuilder Result(*Builder);
+ if (Matcher.matches(*Alias, this, &Result)) {
+ *Builder = std::move(Result);
+ return true;
+ }
}
+ return false;
}
+
+ for (const TypedefNameDecl *Alias : Aliases->second)
+ if (matches(Alias))
+ return true;
return false;
}
@@ -1506,12 +1514,14 @@ bool MatchASTVisitor::TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue) {
return RecursiveASTVisitor<MatchASTVisitor>::TraverseStmt(StmtNode, Queue);
}
-bool MatchASTVisitor::TraverseType(QualType TypeNode) {
+bool MatchASTVisitor::TraverseType(QualType TypeNode, bool TraverseQualifier) {
match(TypeNode);
- return RecursiveASTVisitor<MatchASTVisitor>::TraverseType(TypeNode);
+ return RecursiveASTVisitor<MatchASTVisitor>::TraverseType(TypeNode,
+ TraverseQualifier);
}
-bool MatchASTVisitor::TraverseTypeLoc(TypeLoc TypeLocNode) {
+bool MatchASTVisitor::TraverseTypeLoc(TypeLoc TypeLocNode,
+ bool TraverseQualifier) {
// The RecursiveASTVisitor only visits types if they're not within TypeLocs.
// We still want to find those types via matchers, so we match them here. Note
// that the TypeLocs are structurally a shadow-hierarchy to the expressed
@@ -1519,11 +1529,12 @@ bool MatchASTVisitor::TraverseTypeLoc(TypeLoc TypeLocNode) {
// each TypeLoc.
match(TypeLocNode);
match(TypeLocNode.getType());
- return RecursiveASTVisitor<MatchASTVisitor>::TraverseTypeLoc(TypeLocNode);
+ return RecursiveASTVisitor<MatchASTVisitor>::TraverseTypeLoc(
+ TypeLocNode, TraverseQualifier);
}
-bool MatchASTVisitor::TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) {
- match(*NNS);
+bool MatchASTVisitor::TraverseNestedNameSpecifier(NestedNameSpecifier NNS) {
+ match(NNS);
return RecursiveASTVisitor<MatchASTVisitor>::TraverseNestedNameSpecifier(NNS);
}
@@ -1537,7 +1548,7 @@ bool MatchASTVisitor::TraverseNestedNameSpecifierLoc(
// We only match the nested name specifier here (as opposed to traversing it)
// because the traversal is already done in the parallel "Loc"-hierarchy.
if (NNS.hasQualifier())
- match(*NNS.getNestedNameSpecifier());
+ match(NNS.getNestedNameSpecifier());
return
RecursiveASTVisitor<MatchASTVisitor>::TraverseNestedNameSpecifierLoc(NNS);
}
diff --git a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
index 9cc50a656d37f..cb6397d5ed8eb 100644
--- a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -754,6 +754,8 @@ const internal::VariadicDynCastAllOfMatcher<Decl, TypedefDecl> typedefDecl;
const internal::VariadicDynCastAllOfMatcher<Decl, TypedefNameDecl>
typedefNameDecl;
const internal::VariadicDynCastAllOfMatcher<Decl, TypeAliasDecl> typeAliasDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, UsingShadowDecl>
+ usingShadowDecl;
const internal::VariadicDynCastAllOfMatcher<Decl, TypeAliasTemplateDecl>
typeAliasTemplateDecl;
const internal::VariadicAllOfMatcher<Decl> decl;
@@ -807,8 +809,6 @@ const internal::VariadicDynCastAllOfMatcher<TypeLoc, ReferenceTypeLoc>
const internal::VariadicDynCastAllOfMatcher<TypeLoc,
TemplateSpecializationTypeLoc>
templateSpecializationTypeLoc;
-const internal::VariadicDynCastAllOfMatcher<TypeLoc, ElaboratedTypeLoc>
- elaboratedTypeLoc;
const internal::VariadicDynCastAllOfMatcher<Stmt, UnaryExprOrTypeTraitExpr>
unaryExprOrTypeTraitExpr;
@@ -1099,7 +1099,6 @@ const AstTypeMatcher<TemplateSpecializationType> templateSpecializationType;
const AstTypeMatcher<UnaryTransformType> unaryTransformType;
const AstTypeMatcher<RecordType> recordType;
const AstTypeMatcher<TagType> tagType;
-const AstTypeMatcher<ElaboratedType> elaboratedType;
const AstTypeMatcher<UsingType> usingType;
const AstTypeMatcher<SubstTemplateTypeParmType> substTemplateTypeParmType;
const AstTypeMatcher<TemplateTypeParmType> templateTypeParmType;
diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp
index 562df715e08ae..7f6a6aaed1734 100644
--- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -235,8 +235,6 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(designatorCountIs);
REGISTER_MATCHER(doStmt);
REGISTER_MATCHER(eachOf);
- REGISTER_MATCHER(elaboratedType);
- REGISTER_MATCHER(elaboratedTypeLoc);
REGISTER_MATCHER(usingType);
REGISTER_MATCHER(enumConstantDecl);
REGISTER_MATCHER(enumDecl);
@@ -341,7 +339,6 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(hasMemberName);
REGISTER_MATCHER(hasMethod);
REGISTER_MATCHER(hasName);
- REGISTER_MATCHER(hasNamedTypeLoc);
REGISTER_MATCHER(hasNullSelector);
REGISTER_MATCHER(hasObjectExpression);
REGISTER_MATCHER(hasOperands);
@@ -503,7 +500,6 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(memberHasSameNameAsBoundNode);
REGISTER_MATCHER(memberPointerType);
REGISTER_MATCHER(namedDecl);
- REGISTER_MATCHER(namesType);
REGISTER_MATCHER(namespaceAliasDecl);
REGISTER_MATCHER(namespaceDecl);
REGISTER_MATCHER(nestedNameSpecifier);
@@ -593,6 +589,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(typeLoc);
REGISTER_MATCHER(typedefDecl);
REGISTER_MATCHER(typedefNameDecl);
+ REGISTER_MATCHER(usingShadowDecl);
REGISTER_MATCHER(typedefType);
REGISTER_MATCHER(unaryExprOrTypeTraitExpr);
REGISTER_MATCHER(unaryOperator);
diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
index 256ea18284189..f14cb43e47dd4 100644
--- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -532,9 +532,11 @@ void Environment::initialize() {
} else if (auto *FieldBeingInitialized =
dyn_cast<FieldDecl>(Parent->getLambdaContextDecl())) {
// This is in a field initializer, rather than a method.
+ const RecordDecl *RD = FieldBeingInitialized->getParent();
+ const ASTContext &Ctx = RD->getASTContext();
+ CanQualType T = Ctx.getCanonicalTagType(RD);
setThisPointeeStorageLocation(
- cast<RecordStorageLocation>(createObject(QualType(
- FieldBeingInitialized->getParent()->getTypeForDecl(), 0))));
+ cast<RecordStorageLocation>(createObject(T)));
} else {
assert(false && "Unexpected this-capturing lambda context.");
}
diff --git a/clang/lib/Analysis/ThreadSafety.cpp b/clang/lib/Analysis/ThreadSafety.cpp
index 80e7c8eff671a..5037b75542925 100644
--- a/clang/lib/Analysis/ThreadSafety.cpp
+++ b/clang/lib/Analysis/ThreadSafety.cpp
@@ -1875,7 +1875,9 @@ void BuildLockset::handleCall(const Expr *Exp, const NamedDecl *D,
assert(inserted.second && "Are we visiting the same expression again?");
if (isa<CXXConstructExpr>(Exp))
Self = Placeholder;
- if (TagT->getDecl()->hasAttr<ScopedLockableAttr>())
+ if (TagT->getOriginalDecl()
+ ->getMostRecentDecl()
+ ->hasAttr<ScopedLockableAttr>())
Scp = CapabilityExpr(Placeholder, Exp->getType(), /*Neg=*/false);
}
diff --git a/clang/lib/Analysis/ThreadSafetyCommon.cpp b/clang/lib/Analysis/ThreadSafetyCommon.cpp
index ddbd0a9ca904b..f560dd8ae1dd1 100644
--- a/clang/lib/Analysis/ThreadSafetyCommon.cpp
+++ b/clang/lib/Analysis/ThreadSafetyCommon.cpp
@@ -84,8 +84,8 @@ static std::pair<StringRef, bool> classifyCapability(QualType QT) {
// which it is. The type should either be a record or a typedef, or a pointer
// or reference thereof.
if (const auto *RT = QT->getAs<RecordType>()) {
- if (const auto *RD = RT->getDecl())
- return classifyCapability(*RD);
+ if (const auto *RD = RT->getOriginalDecl())
+ return classifyCapability(*RD->getDefinitionOrSelf());
} else if (const auto *TT = QT->getAs<TypedefType>()) {
if (const auto *TD = TT->getDecl())
return classifyCapability(*TD);
diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp
index 6048169b56640..dc865cbc335b0 100644
--- a/clang/lib/Analysis/UnsafeBufferUsage.cpp
+++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp
@@ -181,18 +181,22 @@ class MatchDescendantVisitor : public DynamicRecursiveASTVisitor {
return DynamicRecursiveASTVisitor::TraverseUnaryExprOrTypeTraitExpr(Node);
}
- bool TraverseTypeOfExprTypeLoc(TypeOfExprTypeLoc Node) override {
+ bool TraverseTypeOfExprTypeLoc(TypeOfExprTypeLoc Node,
+ bool TraverseQualifier) override {
// Unevaluated context.
if (ignoreUnevaluatedContext)
return true;
- return DynamicRecursiveASTVisitor::TraverseTypeOfExprTypeLoc(Node);
+ return DynamicRecursiveASTVisitor::TraverseTypeOfExprTypeLoc(
+ Node, TraverseQualifier);
}
- bool TraverseDecltypeTypeLoc(DecltypeTypeLoc Node) override {
+ bool TraverseDecltypeTypeLoc(DecltypeTypeLoc Node,
+ bool TraverseQualifier) override {
// Unevaluated context.
if (ignoreUnevaluatedContext)
return true;
- return DynamicRecursiveASTVisitor::TraverseDecltypeTypeLoc(Node);
+ return DynamicRecursiveASTVisitor::TraverseDecltypeTypeLoc(
+ Node, TraverseQualifier);
}
bool TraverseCXXNoexceptExpr(CXXNoexceptExpr *Node) override {
diff --git a/clang/lib/CodeGen/ABIInfo.cpp b/clang/lib/CodeGen/ABIInfo.cpp
index d981d69913632..b5d5f46dc5b5d 100644
--- a/clang/lib/CodeGen/ABIInfo.cpp
+++ b/clang/lib/CodeGen/ABIInfo.cpp
@@ -68,7 +68,7 @@ bool ABIInfo::isHomogeneousAggregate(QualType Ty, const Type *&Base,
return false;
Members *= NElements;
} else if (const RecordType *RT = Ty->getAs<RecordType>()) {
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
if (RD->hasFlexibleArrayMember())
return false;
diff --git a/clang/lib/CodeGen/ABIInfoImpl.cpp b/clang/lib/CodeGen/ABIInfoImpl.cpp
index 0a612d3461dc2..79dbe70a0c8eb 100644
--- a/clang/lib/CodeGen/ABIInfoImpl.cpp
+++ b/clang/lib/CodeGen/ABIInfoImpl.cpp
@@ -29,7 +29,7 @@ ABIArgInfo DefaultABIInfo::classifyArgumentType(QualType Ty) const {
// Treat an enum type as its underlying type.
if (const EnumType *EnumTy = Ty->getAs<EnumType>())
- Ty = EnumTy->getDecl()->getIntegerType();
+ Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
ASTContext &Context = getContext();
if (const auto *EIT = Ty->getAs<BitIntType>())
@@ -53,7 +53,7 @@ ABIArgInfo DefaultABIInfo::classifyReturnType(QualType RetTy) const {
// Treat an enum type as its underlying type.
if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
- RetTy = EnumTy->getDecl()->getIntegerType();
+ RetTy = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
if (const auto *EIT = RetTy->getAs<BitIntType>())
if (EIT->getNumBits() >
@@ -105,13 +105,12 @@ llvm::Type *CodeGen::getVAListElementType(CodeGenFunction &CGF) {
CGCXXABI::RecordArgABI CodeGen::getRecordArgABI(const RecordType *RT,
CGCXXABI &CXXABI) {
- const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
- if (!RD) {
- if (!RT->getDecl()->canPassInRegisters())
- return CGCXXABI::RAA_Indirect;
- return CGCXXABI::RAA_Default;
- }
- return CXXABI.getRecordArgABI(RD);
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
+ if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD))
+ return CXXABI.getRecordArgABI(CXXRD);
+ if (!RD->canPassInRegisters())
+ return CGCXXABI::RAA_Indirect;
+ return CGCXXABI::RAA_Default;
}
CGCXXABI::RecordArgABI CodeGen::getRecordArgABI(QualType T, CGCXXABI &CXXABI) {
@@ -125,20 +124,21 @@ bool CodeGen::classifyReturnType(const CGCXXABI &CXXABI, CGFunctionInfo &FI,
const ABIInfo &Info) {
QualType Ty = FI.getReturnType();
- if (const auto *RT = Ty->getAs<RecordType>())
- if (!isa<CXXRecordDecl>(RT->getDecl()) &&
- !RT->getDecl()->canPassInRegisters()) {
+ if (const auto *RT = Ty->getAs<RecordType>()) {
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
+ if (!isa<CXXRecordDecl>(RD) && !RD->canPassInRegisters()) {
FI.getReturnInfo() = Info.getNaturalAlignIndirect(
Ty, Info.getDataLayout().getAllocaAddrSpace());
return true;
}
+ }
return CXXABI.classifyReturnType(FI);
}
QualType CodeGen::useFirstFieldIfTransparentUnion(QualType Ty) {
if (const RecordType *UT = Ty->getAsUnionType()) {
- const RecordDecl *UD = UT->getDecl();
+ const RecordDecl *UD = UT->getOriginalDecl()->getDefinitionOrSelf();
if (UD->hasAttr<TransparentUnionAttr>()) {
assert(!UD->field_empty() && "sema created an empty transparent union");
return UD->field_begin()->getType();
@@ -276,7 +276,7 @@ bool CodeGen::isEmptyField(ASTContext &Context, const FieldDecl *FD,
// according to the Itanium ABI. The exception applies only to records,
// not arrays of records, so we must also check whether we stripped off an
// array type above.
- if (isa<CXXRecordDecl>(RT->getDecl()) &&
+ if (isa<CXXRecordDecl>(RT->getOriginalDecl()) &&
(WasArray || (!AsIfNoUniqueAddr && !FD->hasAttr<NoUniqueAddressAttr>())))
return false;
@@ -288,7 +288,7 @@ bool CodeGen::isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays,
const RecordType *RT = T->getAs<RecordType>();
if (!RT)
return false;
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
if (RD->hasFlexibleArrayMember())
return false;
@@ -320,7 +320,7 @@ bool CodeGen::isEmptyRecordForLayout(const ASTContext &Context, QualType T) {
if (!RT)
return false;
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
// If this is a C++ record, check the bases first.
if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
@@ -344,7 +344,7 @@ const Type *CodeGen::isSingleElementStruct(QualType T, ASTContext &Context) {
if (!RT)
return nullptr;
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
if (RD->hasFlexibleArrayMember())
return nullptr;
@@ -463,7 +463,7 @@ bool CodeGen::isRecordWithSIMDVectorType(ASTContext &Context, QualType Ty) {
const RecordType *RT = Ty->getAs<RecordType>();
if (!RT)
return false;
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
// If this is a C++ record, check the bases first.
if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))
diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp
index f3ddf7bf9a463..7f2f82bc5e62a 100644
--- a/clang/lib/CodeGen/CGBlocks.cpp
+++ b/clang/lib/CodeGen/CGBlocks.cpp
@@ -425,7 +425,8 @@ static bool isSafeForCXXConstantCapture(QualType type) {
// Only records can be unsafe.
if (!recordType) return true;
- const auto *record = cast<CXXRecordDecl>(recordType->getDecl());
+ const auto *record =
+ cast<CXXRecordDecl>(recordType->getOriginalDecl())->getDefinitionOrSelf();
// Maintain semantics for classes with non-trivial dtors or copy ctors.
if (!record->hasTrivialDestructor()) return false;
diff --git a/clang/lib/CodeGen/CGCUDANV.cpp b/clang/lib/CodeGen/CGCUDANV.cpp
index dd26be74e561b..c7f4bf8a21354 100644
--- a/clang/lib/CodeGen/CGCUDANV.cpp
+++ b/clang/lib/CodeGen/CGCUDANV.cpp
@@ -1131,7 +1131,8 @@ void CGNVCUDARuntime::handleVarRegistration(const VarDecl *D,
// Builtin surfaces and textures and their template arguments are
// also registered with CUDA runtime.
const auto *TD = cast<ClassTemplateSpecializationDecl>(
- D->getType()->castAs<RecordType>()->getDecl());
+ D->getType()->castAs<RecordType>()->getOriginalDecl())
+ ->getDefinitionOrSelf();
const TemplateArgumentList &Args = TD->getTemplateArgs();
if (TD->hasAttr<CUDADeviceBuiltinSurfaceTypeAttr>()) {
assert(Args.size() == 2 &&
diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp
index 78a7b021855b7..f9aff893eb0f0 100644
--- a/clang/lib/CodeGen/CGCXX.cpp
+++ b/clang/lib/CodeGen/CGCXX.cpp
@@ -83,8 +83,9 @@ bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) {
if (I.isVirtual()) continue;
// Skip base classes with trivial destructors.
- const auto *Base =
- cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl());
+ const auto *Base = cast<CXXRecordDecl>(
+ I.getType()->castAs<RecordType>()->getOriginalDecl())
+ ->getDefinitionOrSelf();
if (Base->hasTrivialDestructor()) continue;
// If we've already found a base class with a non-trivial
@@ -277,18 +278,18 @@ static CGCallee BuildAppleKextVirtualCall(CodeGenFunction &CGF,
/// BuildAppleKextVirtualCall - This routine is to support gcc's kext ABI making
/// indirect call to virtual functions. It makes the call through indexing
/// into the vtable.
-CGCallee
-CodeGenFunction::BuildAppleKextVirtualCall(const CXXMethodDecl *MD,
- NestedNameSpecifier *Qual,
- llvm::Type *Ty) {
- assert((Qual->getKind() == NestedNameSpecifier::TypeSpec) &&
+CGCallee CodeGenFunction::BuildAppleKextVirtualCall(const CXXMethodDecl *MD,
+ NestedNameSpecifier Qual,
+ llvm::Type *Ty) {
+ assert(Qual.getKind() == NestedNameSpecifier::Kind::Type &&
"BuildAppleKextVirtualCall - bad Qual kind");
- const Type *QTy = Qual->getAsType();
+ const Type *QTy = Qual.getAsType();
QualType T = QualType(QTy, 0);
const RecordType *RT = T->getAs<RecordType>();
assert(RT && "BuildAppleKextVirtualCall - Qual type must be record");
- const auto *RD = cast<CXXRecordDecl>(RT->getDecl());
+ const auto *RD =
+ cast<CXXRecordDecl>(RT->getOriginalDecl())->getDefinitionOrSelf();
if (const auto *DD = dyn_cast<CXXDestructorDecl>(MD))
return BuildAppleKextVirtualDestructorCall(DD, Dtor_Complete, RD);
diff --git a/clang/lib/CodeGen/CGCXXABI.cpp b/clang/lib/CodeGen/CGCXXABI.cpp
index d42e0bb814a88..cca675838644e 100644
--- a/clang/lib/CodeGen/CGCXXABI.cpp
+++ b/clang/lib/CodeGen/CGCXXABI.cpp
@@ -52,7 +52,7 @@ CGCallee CGCXXABI::EmitLoadOfMemberFunctionPointer(
const auto *RD = MPT->getMostRecentCXXRecordDecl();
ThisPtrForCall =
- CGF.getAsNaturalPointerTo(This, CGF.getContext().getRecordType(RD));
+ CGF.getAsNaturalPointerTo(This, CGF.getContext().getCanonicalTagType(RD));
const FunctionProtoType *FPT =
MPT->getPointeeType()->getAs<FunctionProtoType>();
llvm::Constant *FnPtr = llvm::Constant::getNullValue(
@@ -106,7 +106,7 @@ CGCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) {
llvm::Constant *CGCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) {
return GetBogusMemberPointer(CGM.getContext().getMemberPointerType(
- MD->getType(), /*Qualifier=*/nullptr, MD->getParent()));
+ MD->getType(), /*Qualifier=*/std::nullopt, MD->getParent()));
}
llvm::Constant *CGCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index c8c3d6b20c496..6cf67be5206a3 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -125,16 +125,16 @@ unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) {
/// calling a method pointer.
CanQualType CodeGenTypes::DeriveThisType(const CXXRecordDecl *RD,
const CXXMethodDecl *MD) {
- QualType RecTy;
+ CanQualType RecTy;
if (RD)
- RecTy = Context.getTagDeclType(RD)->getCanonicalTypeInternal();
+ RecTy = Context.getCanonicalTagType(RD);
else
RecTy = Context.VoidTy;
if (MD)
- RecTy = Context.getAddrSpaceQualType(
- RecTy, MD->getMethodQualifiers().getAddressSpace());
- return Context.getPointerType(CanQualType::CreateUnsafe(RecTy));
+ RecTy = CanQualType::CreateUnsafe(Context.getAddrSpaceQualType(
+ RecTy, MD->getMethodQualifiers().getAddressSpace()));
+ return Context.getPointerType(RecTy);
}
/// Returns the canonical formal type of the given C++ method.
@@ -1008,7 +1008,7 @@ getTypeExpansion(QualType Ty, const ASTContext &Context) {
if (const RecordType *RT = Ty->getAs<RecordType>()) {
SmallVector<const CXXBaseSpecifier *, 1> Bases;
SmallVector<const FieldDecl *, 1> Fields;
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
assert(!RD->hasFlexibleArrayMember() &&
"Cannot expand structure with flexible array.");
if (RD->isUnion()) {
@@ -1895,7 +1895,7 @@ bool CodeGenModule::MayDropFunctionReturn(const ASTContext &Context,
// complex destructor or a non-trivially copyable type.
if (const RecordType *RT =
ReturnType.getCanonicalType()->getAs<RecordType>()) {
- if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl()))
+ if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getOriginalDecl()))
return ClassDecl->hasTrivialDestructor();
}
return ReturnType.isTriviallyCopyableType(Context);
@@ -3807,7 +3807,7 @@ static void setUsedBits(CodeGenModule &CGM, const RecordType *RTy, int Offset,
SmallVectorImpl<uint64_t> &Bits) {
ASTContext &Context = CGM.getContext();
int CharWidth = Context.getCharWidth();
- const RecordDecl *RD = RTy->getDecl()->getDefinition();
+ const RecordDecl *RD = RTy->getOriginalDecl()->getDefinition();
const ASTRecordLayout &ASTLayout = Context.getASTRecordLayout(RD);
const CGRecordLayout &Layout = CGM.getTypes().getCGRecordLayout(RD);
@@ -4268,7 +4268,10 @@ void CodeGenFunction::EmitDelegateCallArg(CallArgList &args,
// Deactivate the cleanup for the callee-destructed param that was pushed.
if (type->isRecordType() && !CurFuncIsThunk &&
- type->castAs<RecordType>()->getDecl()->isParamDestroyedInCallee() &&
+ type->castAs<RecordType>()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->isParamDestroyedInCallee() &&
param->needsDestruction(getContext())) {
EHScopeStack::stable_iterator cleanup =
CalleeDestructedParamCleanups.lookup(cast<ParmVarDecl>(param));
@@ -4864,8 +4867,10 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E,
// In the Microsoft C++ ABI, aggregate arguments are destructed by the callee.
// However, we still have to push an EH-only cleanup in case we unwind before
// we make it to the call.
- if (type->isRecordType() &&
- type->castAs<RecordType>()->getDecl()->isParamDestroyedInCallee()) {
+ if (type->isRecordType() && type->castAs<RecordType>()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->isParamDestroyedInCallee()) {
// If we're using inalloca, use the argument memory. Otherwise, use a
// temporary.
AggValueSlot Slot = args.isUsingInAlloca()
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index 4a465e6526da0..e9a92ae0f01cb 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/lib/CodeGen/CGClass.cpp
@@ -181,7 +181,9 @@ CharUnits CodeGenModule::computeNonVirtualBaseClassOffset(
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
const auto *BaseDecl =
- cast<CXXRecordDecl>(Base->getType()->castAs<RecordType>()->getDecl());
+ cast<CXXRecordDecl>(
+ Base->getType()->castAs<RecordType>()->getOriginalDecl())
+ ->getDefinitionOrSelf();
// Add the offset.
Offset += Layout.getBaseClassOffset(BaseDecl);
@@ -301,7 +303,8 @@ Address CodeGenFunction::GetAddressOfBaseClass(
// and hence will not require any further steps.
if ((*Start)->isVirtual()) {
VBase = cast<CXXRecordDecl>(
- (*Start)->getType()->castAs<RecordType>()->getDecl());
+ (*Start)->getType()->castAs<RecordType>()->getOriginalDecl())
+ ->getDefinitionOrSelf();
++Start;
}
@@ -326,7 +329,7 @@ Address CodeGenFunction::GetAddressOfBaseClass(
llvm::Type *PtrTy = llvm::PointerType::get(
CGM.getLLVMContext(), Value.getType()->getPointerAddressSpace());
- QualType DerivedTy = getContext().getRecordType(Derived);
+ CanQualType DerivedTy = getContext().getCanonicalTagType(Derived);
CharUnits DerivedAlign = CGM.getClassPointerAlignment(Derived);
// If the static offset is zero and we don't have a virtual step,
@@ -401,8 +404,7 @@ CodeGenFunction::GetAddressOfDerivedClass(Address BaseAddr,
bool NullCheckValue) {
assert(PathBegin != PathEnd && "Base path should not be empty!");
- QualType DerivedTy =
- getContext().getCanonicalType(getContext().getTagDeclType(Derived));
+ CanQualType DerivedTy = getContext().getCanonicalTagType(Derived);
llvm::Type *DerivedValueTy = ConvertType(DerivedTy);
llvm::Value *NonVirtualOffset =
@@ -559,7 +561,8 @@ static void EmitBaseInitializer(CodeGenFunction &CGF,
const Type *BaseType = BaseInit->getBaseClass();
const auto *BaseClassDecl =
- cast<CXXRecordDecl>(BaseType->castAs<RecordType>()->getDecl());
+ cast<CXXRecordDecl>(BaseType->castAs<RecordType>()->getOriginalDecl())
+ ->getDefinitionOrSelf();
bool isBaseVirtual = BaseInit->isBaseVirtual();
@@ -638,7 +641,7 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
QualType FieldType = Field->getType();
llvm::Value *ThisPtr = CGF.LoadCXXThis();
- QualType RecordTy = CGF.getContext().getTypeDeclType(ClassDecl);
+ CanQualType RecordTy = CGF.getContext().getCanonicalTagType(ClassDecl);
LValue LHS;
// If a base constructor is being emitted, create an LValue that has the
@@ -974,7 +977,7 @@ namespace {
}
CharUnits MemcpySize = getMemcpySize(FirstByteOffset);
- QualType RecordTy = CGF.getContext().getTypeDeclType(ClassDecl);
+ CanQualType RecordTy = CGF.getContext().getCanonicalTagType(ClassDecl);
Address ThisPtr = CGF.LoadCXXThisAddress();
LValue DestLV = CGF.MakeAddrLValue(ThisPtr, RecordTy);
LValue Dest = CGF.EmitLValueForFieldInitialization(DestLV, FirstField);
@@ -1122,7 +1125,7 @@ namespace {
void pushEHDestructors() {
Address ThisPtr = CGF.LoadCXXThisAddress();
- QualType RecordTy = CGF.getContext().getTypeDeclType(ClassDecl);
+ CanQualType RecordTy = CGF.getContext().getCanonicalTagType(ClassDecl);
LValue LHS = CGF.MakeAddrLValue(ThisPtr, RecordTy);
for (unsigned i = 0; i < AggregatedInits.size(); ++i) {
@@ -1265,7 +1268,8 @@ namespace {
static bool isInitializerOfDynamicClass(const CXXCtorInitializer *BaseInit) {
const Type *BaseType = BaseInit->getBaseClass();
const auto *BaseClassDecl =
- cast<CXXRecordDecl>(BaseType->castAs<RecordType>()->getDecl());
+ cast<CXXRecordDecl>(BaseType->castAs<RecordType>()->getOriginalDecl())
+ ->getDefinitionOrSelf();
return BaseClassDecl->isDynamicClass();
}
@@ -1374,7 +1378,9 @@ HasTrivialDestructorBody(ASTContext &Context,
continue;
const CXXRecordDecl *NonVirtualBase =
- cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl());
+ cast<CXXRecordDecl>(
+ I.getType()->castAs<RecordType>()->getOriginalDecl())
+ ->getDefinitionOrSelf();
if (!HasTrivialDestructorBody(Context, NonVirtualBase,
MostDerivedClassDecl))
return false;
@@ -1383,8 +1389,10 @@ HasTrivialDestructorBody(ASTContext &Context,
if (BaseClassDecl == MostDerivedClassDecl) {
// Check virtual bases.
for (const auto &I : BaseClassDecl->vbases()) {
- const CXXRecordDecl *VirtualBase =
- cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl());
+ const auto *VirtualBase =
+ cast<CXXRecordDecl>(
+ I.getType()->castAs<RecordType>()->getOriginalDecl())
+ ->getDefinitionOrSelf();
if (!HasTrivialDestructorBody(Context, VirtualBase,
MostDerivedClassDecl))
return false;
@@ -1404,7 +1412,8 @@ FieldHasTrivialDestructorBody(ASTContext &Context,
if (!RT)
return true;
- CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+ auto *FieldClassDecl =
+ cast<CXXRecordDecl>(RT->getOriginalDecl())->getDefinitionOrSelf();
// The destructor for an implicit anonymous union member is never invoked.
if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
@@ -1588,7 +1597,7 @@ namespace {
const CXXRecordDecl *ClassDecl = Dtor->getParent();
CGF.EmitDeleteCall(Dtor->getOperatorDelete(),
LoadThisForDtorDelete(CGF, Dtor),
- CGF.getContext().getTagDeclType(ClassDecl));
+ CGF.getContext().getCanonicalTagType(ClassDecl));
}
};
@@ -1606,7 +1615,7 @@ namespace {
const CXXRecordDecl *ClassDecl = Dtor->getParent();
CGF.EmitDeleteCall(Dtor->getOperatorDelete(),
LoadThisForDtorDelete(CGF, Dtor),
- CGF.getContext().getTagDeclType(ClassDecl));
+ CGF.getContext().getCanonicalTagType(ClassDecl));
assert(Dtor->getOperatorDelete()->isDestroyingOperatorDelete() ==
ReturnAfterDelete &&
"unexpected value for ReturnAfterDelete");
@@ -1647,7 +1656,8 @@ namespace {
void Emit(CodeGenFunction &CGF, Flags flags) override {
// Find the address of the field.
Address thisValue = CGF.LoadCXXThisAddress();
- QualType RecordTy = CGF.getContext().getTagDeclType(field->getParent());
+ CanQualType RecordTy =
+ CGF.getContext().getCanonicalTagType(field->getParent());
LValue ThisLV = CGF.MakeAddrLValue(thisValue, RecordTy);
LValue LV = CGF.EmitLValueForField(ThisLV, field);
assert(LV.isSimple());
@@ -1870,7 +1880,7 @@ void CodeGenFunction::EnterDtorCleanups(const CXXDestructorDecl *DD,
const CXXRecordDecl *ClassDecl = DD->getParent();
EmitDeleteCall(DD->getOperatorDelete(),
LoadThisForDtorDelete(*this, DD),
- getContext().getTagDeclType(ClassDecl));
+ getContext().getCanonicalTagType(ClassDecl));
EmitBranchThroughCleanup(ReturnBlock);
} else {
EHStack.pushCleanup<CallDtorDelete>(NormalAndEHCleanup);
@@ -1898,7 +1908,9 @@ void CodeGenFunction::EnterDtorCleanups(const CXXDestructorDecl *DD,
// the reverse order.
for (const auto &Base : ClassDecl->vbases()) {
auto *BaseClassDecl =
- cast<CXXRecordDecl>(Base.getType()->castAs<RecordType>()->getDecl());
+ cast<CXXRecordDecl>(
+ Base.getType()->castAs<RecordType>()->getOriginalDecl())
+ ->getDefinitionOrSelf();
if (BaseClassDecl->hasTrivialDestructor()) {
// Under SanitizeMemoryUseAfterDtor, poison the trivial base class
@@ -1964,7 +1976,7 @@ void CodeGenFunction::EnterDtorCleanups(const CXXDestructorDecl *DD,
// Anonymous union members do not have their destructors called.
const RecordType *RT = type->getAsUnionType();
- if (RT && RT->getDecl()->isAnonymousStructOrUnion())
+ if (RT && RT->getOriginalDecl()->isAnonymousStructOrUnion())
continue;
CleanupKind cleanupKind = getCleanupKind(dtorKind);
@@ -2057,7 +2069,7 @@ void CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor,
//
// Note that these are complete objects and so we don't need to
// use the non-virtual size or alignment.
- QualType type = getContext().getTypeDeclType(ctor->getParent());
+ CanQualType type = getContext().getCanonicalTagType(ctor->getParent());
CharUnits eltAlignment =
arrayBase.getAlignment()
.alignmentOfArrayElement(getContext().getTypeSizeInChars(type));
@@ -2119,7 +2131,8 @@ void CodeGenFunction::destroyCXXObject(CodeGenFunction &CGF,
Address addr,
QualType type) {
const RecordType *rtype = type->castAs<RecordType>();
- const CXXRecordDecl *record = cast<CXXRecordDecl>(rtype->getDecl());
+ const auto *record =
+ cast<CXXRecordDecl>(rtype->getOriginalDecl())->getDefinitionOrSelf();
const CXXDestructorDecl *dtor = record->getDestructor();
assert(!dtor->isTrivial());
CGF.EmitCXXDestructorCall(dtor, Dtor_Complete, /*for vbase*/ false,
@@ -2158,7 +2171,7 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
const Expr *Arg = E->getArg(0);
LValue Src = EmitLValue(Arg);
- QualType DestTy = getContext().getTypeDeclType(D->getParent());
+ CanQualType DestTy = getContext().getCanonicalTagType(D->getParent());
LValue Dest = MakeAddrLValue(This, DestTy);
EmitAggregateCopyCtor(Dest, Src, ThisAVS.mayOverlap());
return;
@@ -2210,7 +2223,8 @@ void CodeGenFunction::EmitCXXConstructorCall(
if (!NewPointerIsChecked)
EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, Loc, This,
- getContext().getRecordType(ClassDecl), CharUnits::Zero());
+ getContext().getCanonicalTagType(ClassDecl),
+ CharUnits::Zero());
if (D->isTrivial() && D->isDefaultConstructor()) {
assert(Args.size() == 1 && "trivial default ctor with args");
@@ -2226,7 +2240,7 @@ void CodeGenFunction::EmitCXXConstructorCall(
Address Src = makeNaturalAddressForPointer(
Args[1].getRValue(*this).getScalarVal(), SrcTy);
LValue SrcLVal = MakeAddrLValue(Src, SrcTy);
- QualType DestTy = getContext().getTypeDeclType(ClassDecl);
+ CanQualType DestTy = getContext().getCanonicalTagType(ClassDecl);
LValue DestLVal = MakeAddrLValue(This, DestTy);
EmitAggregateCopyCtor(DestLVal, SrcLVal, Overlap);
return;
@@ -2638,8 +2652,9 @@ void CodeGenFunction::getVTablePointers(BaseSubobject Base,
// Traverse bases.
for (const auto &I : RD->bases()) {
- auto *BaseDecl =
- cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl());
+ auto *BaseDecl = cast<CXXRecordDecl>(
+ I.getType()->castAs<RecordType>()->getOriginalDecl())
+ ->getDefinitionOrSelf();
// Ignore classes without a vtable.
if (!BaseDecl->isDynamicClass())
@@ -2772,7 +2787,7 @@ void CodeGenFunction::EmitTypeMetadataCodeForVCall(const CXXRecordDecl *RD,
// Don't insert type test assumes if we are forcing public
// visibility.
!CGM.AlwaysHasLTOVisibilityPublic(RD)) {
- QualType Ty = QualType(RD->getTypeForDecl(), 0);
+ CanQualType Ty = CGM.getContext().getCanonicalTagType(RD);
llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(Ty);
llvm::Value *TypeId =
llvm::MetadataAsValue::get(CGM.getLLVMContext(), MD);
@@ -2839,7 +2854,8 @@ void CodeGenFunction::EmitVTablePtrCheckForCast(QualType T, Address Derived,
if (!ClassTy)
return;
- const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(ClassTy->getDecl());
+ const auto *ClassDecl =
+ cast<CXXRecordDecl>(ClassTy->getOriginalDecl())->getDefinitionOrSelf();
if (!ClassDecl->isCompleteDefinition() || !ClassDecl->isDynamicClass())
return;
@@ -2896,8 +2912,8 @@ void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD,
EmitSanitizerStatReport(SSK);
- llvm::Metadata *MD =
- CGM.CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0));
+ CanQualType T = CGM.getContext().getCanonicalTagType(RD);
+ llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(T);
llvm::Value *TypeId = llvm::MetadataAsValue::get(getLLVMContext(), MD);
llvm::Value *TypeTest = Builder.CreateCall(
@@ -2906,7 +2922,7 @@ void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD,
llvm::Constant *StaticData[] = {
llvm::ConstantInt::get(Int8Ty, TCK),
EmitCheckSourceLocation(Loc),
- EmitCheckTypeDescriptor(QualType(RD->getTypeForDecl(), 0)),
+ EmitCheckTypeDescriptor(T),
};
auto CrossDsoTypeId = CGM.CreateCrossDsoCfiTypeId(MD);
@@ -2956,8 +2972,8 @@ llvm::Value *CodeGenFunction::EmitVTableTypeCheckedLoad(
EmitSanitizerStatReport(llvm::SanStat_CFI_VCall);
- llvm::Metadata *MD =
- CGM.CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0));
+ CanQualType T = CGM.getContext().getCanonicalTagType(RD);
+ llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(T);
llvm::Value *TypeId = llvm::MetadataAsValue::get(CGM.getLLVMContext(), MD);
auto CheckedLoadIntrinsic = CGM.getVTables().useRelativeLayout()
@@ -3039,7 +3055,8 @@ void CodeGenFunction::EmitLambdaBlockInvokeBody() {
// Start building arguments for forwarding call
CallArgList CallArgs;
- QualType ThisType = getContext().getPointerType(getContext().getRecordType(Lambda));
+ CanQualType ThisType =
+ getContext().getPointerType(getContext().getCanonicalTagType(Lambda));
Address ThisPtr = GetAddrOfBlockDecl(variable);
CallArgs.add(RValue::get(getAsNaturalPointerTo(ThisPtr, ThisType)), ThisType);
@@ -3066,8 +3083,8 @@ void CodeGenFunction::EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD) {
// Start building arguments for forwarding call
CallArgList CallArgs;
- QualType LambdaType = getContext().getRecordType(Lambda);
- QualType ThisType = getContext().getPointerType(LambdaType);
+ CanQualType LambdaType = getContext().getCanonicalTagType(Lambda);
+ CanQualType ThisType = getContext().getPointerType(LambdaType);
Address ThisPtr = CreateMemTemp(LambdaType, "unused.capture");
CallArgs.add(RValue::get(ThisPtr.emitRawPointer(*this)), ThisType);
@@ -3118,8 +3135,8 @@ void CodeGenFunction::EmitLambdaInAllocaCallOpBody(const CXXMethodDecl *MD) {
// Forward %this argument.
CallArgList CallArgs;
- QualType LambdaType = getContext().getRecordType(MD->getParent());
- QualType ThisType = getContext().getPointerType(LambdaType);
+ CanQualType LambdaType = getContext().getCanonicalTagType(MD->getParent());
+ CanQualType ThisType = getContext().getPointerType(LambdaType);
llvm::Value *ThisArg = CurFn->getArg(0);
CallArgs.add(RValue::get(ThisArg), ThisType);
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 8bf7d24d8551d..2df95d59cc8cf 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -369,7 +369,7 @@ llvm::DIScope *CGDebugInfo::getContextDescriptor(const Decl *Context,
if (const auto *RDecl = dyn_cast<RecordDecl>(Context))
if (!RDecl->isDependentType())
- return getOrCreateType(CGM.getContext().getTypeDeclType(RDecl),
+ return getOrCreateType(CGM.getContext().getCanonicalTagType(RDecl),
TheCU->getFile());
return Default;
}
@@ -1294,7 +1294,7 @@ static bool needsTypeIdentifier(const TagDecl *TD, CodeGenModule &CGM,
static SmallString<256> getTypeIdentifier(const TagType *Ty, CodeGenModule &CGM,
llvm::DICompileUnit *TheCU) {
SmallString<256> Identifier;
- const TagDecl *TD = Ty->getDecl();
+ const TagDecl *TD = Ty->getOriginalDecl()->getDefinitionOrSelf();
if (!needsTypeIdentifier(TD, CGM, TheCU))
return Identifier;
@@ -1330,8 +1330,8 @@ static llvm::dwarf::Tag getTagForRecord(const RecordDecl *RD) {
llvm::DICompositeType *
CGDebugInfo::getOrCreateRecordFwdDecl(const RecordType *Ty,
llvm::DIScope *Ctx) {
- const RecordDecl *RD = Ty->getDecl();
- if (llvm::DIType *T = getTypeOrNull(CGM.getContext().getRecordType(RD)))
+ const RecordDecl *RD = Ty->getOriginalDecl()->getDefinitionOrSelf();
+ if (llvm::DIType *T = getTypeOrNull(QualType(Ty, 0)))
return cast<llvm::DICompositeType>(T);
llvm::DIFile *DefUnit = getOrCreateFile(RD->getLocation());
const unsigned Line =
@@ -2024,6 +2024,8 @@ void CGDebugInfo::CollectRecordNestedType(
const TypeDecl *TD, SmallVectorImpl<llvm::Metadata *> &elements) {
QualType Ty = CGM.getContext().getTypeDeclType(TD);
// Injected class names are not considered nested records.
+ // FIXME: Is this supposed to be testing for injected class name declarations
+ // instead?
if (isa<InjectedClassNameType>(Ty))
return;
SourceLocation Loc = TD->getLocation();
@@ -2365,7 +2367,9 @@ void CGDebugInfo::CollectCXXBasesAux(
const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
for (const auto &BI : Bases) {
const auto *Base =
- cast<CXXRecordDecl>(BI.getType()->castAs<RecordType>()->getDecl());
+ cast<CXXRecordDecl>(
+ BI.getType()->castAs<RecordType>()->getOriginalDecl())
+ ->getDefinition();
if (!SeenTypes.insert(Base).second)
continue;
auto *BaseTy = getOrCreateType(BI.getType(), Unit);
@@ -2831,12 +2835,12 @@ void CGDebugInfo::addHeapAllocSiteMetadata(llvm::CallBase *CI,
void CGDebugInfo::completeType(const EnumDecl *ED) {
if (DebugKind <= llvm::codegenoptions::DebugLineTablesOnly)
return;
- QualType Ty = CGM.getContext().getEnumType(ED);
+ CanQualType Ty = CGM.getContext().getCanonicalTagType(ED);
void *TyPtr = Ty.getAsOpaquePtr();
auto I = TypeCache.find(TyPtr);
if (I == TypeCache.end() || !cast<llvm::DIType>(I->second)->isForwardDecl())
return;
- llvm::DIType *Res = CreateTypeDefinition(Ty->castAs<EnumType>());
+ llvm::DIType *Res = CreateTypeDefinition(dyn_cast<EnumType>(Ty));
assert(!Res->isForwardDecl());
TypeCache[TyPtr].reset(Res);
}
@@ -2906,7 +2910,7 @@ void CGDebugInfo::completeClassData(const RecordDecl *RD) {
void CGDebugInfo::completeClass(const RecordDecl *RD) {
if (DebugKind <= llvm::codegenoptions::DebugLineTablesOnly)
return;
- QualType Ty = CGM.getContext().getRecordType(RD);
+ CanQualType Ty = CGM.getContext().getCanonicalTagType(RD);
void *TyPtr = Ty.getAsOpaquePtr();
auto I = TypeCache.find(TyPtr);
if (I != TypeCache.end() && !cast<llvm::DIType>(I->second)->isForwardDecl())
@@ -2915,7 +2919,7 @@ void CGDebugInfo::completeClass(const RecordDecl *RD) {
// We want the canonical definition of the structure to not
// be the typedef. Since that would lead to circular typedef
// metadata.
- auto [Res, PrefRes] = CreateTypeDefinition(Ty->castAs<RecordType>());
+ auto [Res, PrefRes] = CreateTypeDefinition(dyn_cast<RecordType>(Ty));
assert(!Res->isForwardDecl());
TypeCache[TyPtr].reset(Res);
}
@@ -3019,14 +3023,14 @@ void CGDebugInfo::completeRequiredType(const RecordDecl *RD) {
if (shouldOmitDefinition(DebugKind, DebugTypeExtRefs, RD, CGM.getLangOpts()))
return;
- QualType Ty = CGM.getContext().getRecordType(RD);
+ CanQualType Ty = CGM.getContext().getCanonicalTagType(RD);
llvm::DIType *T = getTypeOrNull(Ty);
if (T && T->isForwardDecl())
completeClassData(RD);
}
llvm::DIType *CGDebugInfo::CreateType(const RecordType *Ty) {
- RecordDecl *RD = Ty->getDecl();
+ RecordDecl *RD = Ty->getOriginalDecl()->getDefinitionOrSelf();
llvm::DIType *T = cast_or_null<llvm::DIType>(getTypeOrNull(QualType(Ty, 0)));
if (T || shouldOmitDefinition(DebugKind, DebugTypeExtRefs, RD,
CGM.getLangOpts())) {
@@ -3054,7 +3058,7 @@ llvm::DIType *CGDebugInfo::GetPreferredNameType(const CXXRecordDecl *RD,
std::pair<llvm::DIType *, llvm::DIType *>
CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) {
- RecordDecl *RD = Ty->getDecl();
+ RecordDecl *RD = Ty->getOriginalDecl()->getDefinitionOrSelf();
// Get overall information about the record type for the debug info.
llvm::DIFile *DefUnit = getOrCreateFile(RD->getLocation());
@@ -3076,7 +3080,7 @@ CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) {
// Push the struct on region stack.
LexicalBlockStack.emplace_back(&*FwdDecl);
- RegionMap[Ty->getDecl()].reset(FwdDecl);
+ RegionMap[RD].reset(FwdDecl);
// Convert all the elements.
SmallVector<llvm::Metadata *, 16> EltTys;
@@ -3098,7 +3102,7 @@ CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) {
CollectCXXMemberFunctions(CXXDecl, DefUnit, EltTys, FwdDecl);
LexicalBlockStack.pop_back();
- RegionMap.erase(Ty->getDecl());
+ RegionMap.erase(RD);
llvm::DINodeArray Elements = DBuilder.getOrCreateArray(EltTys);
DBuilder.replaceArrays(FwdDecl, Elements);
@@ -3107,7 +3111,7 @@ CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) {
FwdDecl =
llvm::MDNode::replaceWithPermanent(llvm::TempDICompositeType(FwdDecl));
- RegionMap[Ty->getDecl()].reset(FwdDecl);
+ RegionMap[RD].reset(FwdDecl);
if (CGM.getCodeGenOpts().getDebuggerTuning() == llvm::DebuggerKind::LLDB)
if (auto *PrefDI = GetPreferredNameType(CXXDecl, DefUnit))
@@ -3654,8 +3658,9 @@ llvm::DIType *CGDebugInfo::CreateType(const MemberPointerType *Ty,
}
}
- llvm::DIType *ClassType = getOrCreateType(
- QualType(Ty->getMostRecentCXXRecordDecl()->getTypeForDecl(), 0), U);
+ CanQualType T =
+ CGM.getContext().getCanonicalTagType(Ty->getMostRecentCXXRecordDecl());
+ llvm::DIType *ClassType = getOrCreateType(T, U);
if (Ty->isMemberDataPointerType())
return DBuilder.createMemberPointerType(
getOrCreateType(Ty->getPointeeType(), U), ClassType, Size, /*Align=*/0,
@@ -3690,17 +3695,21 @@ llvm::DIType *CGDebugInfo::CreateType(const HLSLInlineSpirvType *Ty,
return nullptr;
}
-llvm::DIType *CGDebugInfo::CreateEnumType(const EnumType *Ty) {
- const EnumDecl *ED = Ty->getDecl();
+static auto getEnumInfo(CodeGenModule &CGM, llvm::DICompileUnit *TheCU,
+ const EnumType *Ty) {
+ const EnumDecl *ED = Ty->getOriginalDecl()->getDefinitionOrSelf();
uint64_t Size = 0;
uint32_t Align = 0;
- if (!ED->getTypeForDecl()->isIncompleteType()) {
- Size = CGM.getContext().getTypeSize(ED->getTypeForDecl());
+ if (ED->isComplete()) {
+ Size = CGM.getContext().getTypeSize(QualType(Ty, 0));
Align = getDeclAlignIfRequired(ED, CGM.getContext());
}
+ return std::make_tuple(ED, Size, Align, getTypeIdentifier(Ty, CGM, TheCU));
+}
- SmallString<256> Identifier = getTypeIdentifier(Ty, CGM, TheCU);
+llvm::DIType *CGDebugInfo::CreateEnumType(const EnumType *Ty) {
+ auto [ED, Size, Align, Identifier] = getEnumInfo(CGM, TheCU, Ty);
bool isImportedFromModule =
DebugTypeExtRefs && ED->isFromASTFile() && ED->getDefinition();
@@ -3735,15 +3744,7 @@ llvm::DIType *CGDebugInfo::CreateEnumType(const EnumType *Ty) {
}
llvm::DIType *CGDebugInfo::CreateTypeDefinition(const EnumType *Ty) {
- const EnumDecl *ED = Ty->getDecl();
- uint64_t Size = 0;
- uint32_t Align = 0;
- if (!ED->getTypeForDecl()->isIncompleteType()) {
- Size = CGM.getContext().getTypeSize(ED->getTypeForDecl());
- Align = getDeclAlignIfRequired(ED, CGM.getContext());
- }
-
- SmallString<256> Identifier = getTypeIdentifier(Ty, CGM, TheCU);
+ auto [ED, Size, Align, Identifier] = getEnumInfo(CGM, TheCU, Ty);
SmallVector<llvm::Metadata *, 16> Enumerators;
ED = ED->getDefinition();
@@ -3818,6 +3819,11 @@ static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) {
switch (T->getTypeClass()) {
default:
return C.getQualifiedType(T.getTypePtr(), Quals);
+ case Type::Enum:
+ case Type::Record:
+ case Type::InjectedClassName:
+ return C.getQualifiedType(T->getCanonicalTypeUnqualified().getTypePtr(),
+ Quals);
case Type::TemplateSpecialization: {
const auto *Spec = cast<TemplateSpecializationType>(T);
if (Spec->isTypeAlias())
@@ -3846,11 +3852,8 @@ static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) {
case Type::CountAttributed:
T = cast<CountAttributedType>(T)->desugar();
break;
- case Type::Elaborated:
- T = cast<ElaboratedType>(T)->getNamedType();
- break;
case Type::Using:
- T = cast<UsingType>(T)->getUnderlyingType();
+ T = cast<UsingType>(T)->desugar();
break;
case Type::Paren:
T = cast<ParenType>(T)->getInnerType();
@@ -3909,7 +3912,8 @@ void CGDebugInfo::completeUnusedClass(const CXXRecordDecl &D) {
completeClassData(&D);
// In case this type has no member function definitions being emitted, ensure
// it is retained
- RetainedTypes.push_back(CGM.getContext().getRecordType(&D).getAsOpaquePtr());
+ RetainedTypes.push_back(
+ CGM.getContext().getCanonicalTagType(&D).getAsOpaquePtr());
}
llvm::DIType *CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile *Unit) {
@@ -4053,7 +4057,6 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
case Type::Adjusted:
case Type::Decayed:
case Type::DeducedTemplateSpecialization:
- case Type::Elaborated:
case Type::Using:
case Type::Paren:
case Type::MacroQualified:
@@ -4096,7 +4099,7 @@ CGDebugInfo::getOrCreateLimitedType(const RecordType *Ty) {
// TODO: Currently used for context chains when limiting debug info.
llvm::DICompositeType *CGDebugInfo::CreateLimitedType(const RecordType *Ty) {
- RecordDecl *RD = Ty->getDecl();
+ RecordDecl *RD = Ty->getOriginalDecl()->getDefinitionOrSelf();
// Get overall information about the record type for the debug info.
StringRef RDName = getClassName(RD);
@@ -4113,7 +4116,7 @@ llvm::DICompositeType *CGDebugInfo::CreateLimitedType(const RecordType *Ty) {
// If we ended up creating the type during the context chain construction,
// just return that.
auto *T = cast_or_null<llvm::DICompositeType>(
- getTypeOrNull(CGM.getContext().getRecordType(RD)));
+ getTypeOrNull(CGM.getContext().getCanonicalTagType(RD)));
if (T && (!T->isForwardDecl() || !RD->getDefinition()))
return T;
@@ -4183,7 +4186,7 @@ llvm::DICompositeType *CGDebugInfo::CreateLimitedType(const RecordType *Ty) {
break;
}
- RegionMap[Ty->getDecl()].reset(RealDecl);
+ RegionMap[RD].reset(RealDecl);
TypeCache[QualType(Ty, 0).getAsOpaquePtr()].reset(RealDecl);
if (const auto *TSpecial = dyn_cast<ClassTemplateSpecializationDecl>(RD))
@@ -4207,8 +4210,8 @@ void CGDebugInfo::CollectContainingType(const CXXRecordDecl *RD,
else
break;
}
- ContainingType = getOrCreateType(QualType(PBase->getTypeForDecl(), 0),
- getOrCreateFile(RD->getLocation()));
+ CanQualType T = CGM.getContext().getCanonicalTagType(PBase);
+ ContainingType = getOrCreateType(T, getOrCreateFile(RD->getLocation()));
} else if (RD->isDynamicClass())
ContainingType = RealDecl;
@@ -4414,9 +4417,10 @@ llvm::DINode *CGDebugInfo::getDeclarationOrDefinition(const Decl *D) {
// we would otherwise do to get a type for a pointee. (forward declarations in
// limited debug info, full definitions (if the type definition is available)
// in unlimited debug info)
- if (const auto *TD = dyn_cast<TypeDecl>(D))
- return getOrCreateType(CGM.getContext().getTypeDeclType(TD),
- getOrCreateFile(TD->getLocation()));
+ if (const auto *TD = dyn_cast<TypeDecl>(D)) {
+ QualType Ty = CGM.getContext().getTypeDeclType(TD);
+ return getOrCreateType(Ty, getOrCreateFile(TD->getLocation()));
+ }
auto I = DeclCache.find(D->getCanonicalDecl());
if (I != DeclCache.end()) {
@@ -5074,7 +5078,7 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const VarDecl *VD,
} else if (const auto *RT = dyn_cast<RecordType>(VD->getType())) {
// If VD is an anonymous union then Storage represents value for
// all union fields.
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
if (RD->isUnion() && RD->isAnonymousStructOrUnion()) {
// GDB has trouble finding local variables in anonymous unions, so we emit
// artificial local variables for each of the members.
@@ -5531,7 +5535,7 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
cast_or_null<CXXMethodDecl>(blockDecl->getNonClosureContext()))
type = Method->getThisType();
else if (auto *RDecl = dyn_cast<CXXRecordDecl>(blockDecl->getParent()))
- type = QualType(RDecl->getTypeForDecl(), 0);
+ type = CGM.getContext().getCanonicalTagType(RDecl);
else
llvm_unreachable("unexpected block declcontext");
@@ -5620,8 +5624,9 @@ llvm::DIGlobalVariableExpression *CGDebugInfo::CollectAnonRecordDecls(
// Ignore unnamed fields, but recurse into anonymous records.
if (FieldName.empty()) {
if (const auto *RT = dyn_cast<RecordType>(Field->getType()))
- GVE = CollectAnonRecordDecls(RT->getDecl(), Unit, LineNo, LinkageName,
- Var, DContext);
+ GVE =
+ CollectAnonRecordDecls(RT->getOriginalDecl()->getDefinitionOrSelf(),
+ Unit, LineNo, LinkageName, Var, DContext);
continue;
}
// Use VarDecl's Tag, Scope and Line number.
@@ -5640,7 +5645,7 @@ static bool ReferencesAnonymousEntity(RecordType *RT) {
// But so long as it's not one of those, it doesn't matter if some sub-type
// of the record (a template parameter) can't be reconstituted - because the
// un-reconstitutable type itself will carry its own name.
- const auto *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
+ const auto *RD = dyn_cast<CXXRecordDecl>(RT->getOriginalDecl());
if (!RD)
return false;
if (!RD->getIdentifier())
@@ -5699,15 +5704,15 @@ struct ReconstitutableType : public RecursiveASTVisitor<ReconstitutableType> {
}
return true;
}
- bool TraverseEnumType(EnumType *ET) {
+ bool TraverseEnumType(EnumType *ET, bool = false) {
// Unnamed enums can't be reconstituted due to a lack of column info we
// produce in the DWARF, so we can't get Clang's full name back.
- if (const auto *ED = dyn_cast<EnumDecl>(ET->getDecl())) {
+ if (const auto *ED = dyn_cast<EnumDecl>(ET->getOriginalDecl())) {
if (!ED->getIdentifier()) {
Reconstitutable = false;
return false;
}
- if (!ED->isExternallyVisible()) {
+ if (!ED->getDefinitionOrSelf()->isExternallyVisible()) {
Reconstitutable = false;
return false;
}
@@ -5720,7 +5725,7 @@ struct ReconstitutableType : public RecursiveASTVisitor<ReconstitutableType> {
Reconstitutable &= !FT->getNoReturnAttr();
return Reconstitutable;
}
- bool VisitRecordType(RecordType *RT) {
+ bool VisitRecordType(RecordType *RT, bool = false) {
if (ReferencesAnonymousEntity(RT)) {
Reconstitutable = false;
return false;
@@ -5903,7 +5908,8 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
// variable for each member of the anonymous union so that it's possible
// to find the name of any field in the union.
if (T->isUnionType() && DeclName.empty()) {
- const RecordDecl *RD = T->castAs<RecordType>()->getDecl();
+ const RecordDecl *RD =
+ T->castAs<RecordType>()->getOriginalDecl()->getDefinitionOrSelf();
assert(RD->isAnonymousStructOrUnion() &&
"unnamed non-anonymous struct or union?");
GVE = CollectAnonRecordDecls(RD, Unit, LineNo, LinkageName, Var, DContext);
@@ -5950,8 +5956,6 @@ void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, const APValue &Init) {
if (const auto *ECD = dyn_cast<EnumConstantDecl>(VD)) {
const auto *ED = cast<EnumDecl>(ECD->getDeclContext());
- assert(isa<EnumType>(ED->getTypeForDecl()) && "Enum without EnumType?");
-
if (CGM.getCodeGenOpts().EmitCodeView) {
// If CodeView, emit enums as global variables, unless they are defined
// inside a class. We do this because MSVC doesn't emit S_CONSTANTs for
@@ -5963,10 +5967,9 @@ void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, const APValue &Init) {
// If not CodeView, emit DW_TAG_enumeration_type if necessary. For
// example: for "enum { ZERO };", a DW_TAG_enumeration_type is created the
// first time `ZERO` is referenced in a function.
- llvm::DIType *EDTy =
- getOrCreateType(QualType(ED->getTypeForDecl(), 0), Unit);
- assert (EDTy->getTag() == llvm::dwarf::DW_TAG_enumeration_type);
- (void)EDTy;
+ CanQualType T = CGM.getContext().getCanonicalTagType(ED);
+ [[maybe_unused]] llvm::DIType *EDTy = getOrCreateType(T, Unit);
+ assert(EDTy->getTag() == llvm::dwarf::DW_TAG_enumeration_type);
return;
}
}
@@ -5985,7 +5988,7 @@ void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, const APValue &Init) {
// FIXME: This is probably unnecessary, since Ty should reference RD
// through its scope.
RetainedTypes.push_back(
- CGM.getContext().getRecordType(RD).getAsOpaquePtr());
+ CGM.getContext().getCanonicalTagType(RD).getAsOpaquePtr());
return;
}
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 04f13c7d7a6a3..55155ada9b9c7 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -113,12 +113,14 @@ void CodeGenFunction::EmitDecl(const Decl &D, bool EvaluateConditionDecl) {
case Decl::CXXRecord: // struct/union/class X; [C++]
if (CGDebugInfo *DI = getDebugInfo())
if (cast<RecordDecl>(D).getDefinition())
- DI->EmitAndRetainType(getContext().getRecordType(cast<RecordDecl>(&D)));
+ DI->EmitAndRetainType(
+ getContext().getCanonicalTagType(cast<RecordDecl>(&D)));
return;
case Decl::Enum: // enum X;
if (CGDebugInfo *DI = getDebugInfo())
if (cast<EnumDecl>(D).getDefinition())
- DI->EmitAndRetainType(getContext().getEnumType(cast<EnumDecl>(&D)));
+ DI->EmitAndRetainType(
+ getContext().getCanonicalTagType(cast<EnumDecl>(&D)));
return;
case Decl::Function: // void X();
case Decl::EnumConstant: // enum ? { X = ? }
@@ -1567,7 +1569,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
;
if (const RecordType *RecordTy = Ty->getAs<RecordType>()) {
- const auto *RD = RecordTy->getDecl();
+ const auto *RD = RecordTy->getOriginalDecl()->getDefinitionOrSelf();
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD);
if ((CXXRD && !CXXRD->hasTrivialDestructor()) ||
RD->isNonTrivialToPrimitiveDestroy()) {
@@ -2727,7 +2729,10 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg,
// Don't push a cleanup in a thunk for a method that will also emit a
// cleanup.
if (Ty->isRecordType() && !CurFuncIsThunk &&
- Ty->castAs<RecordType>()->getDecl()->isParamDestroyedInCallee()) {
+ Ty->castAs<RecordType>()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->isParamDestroyedInCallee()) {
if (QualType::DestructionKind DtorKind =
D.needsDestruction(getContext())) {
assert((DtorKind == QualType::DK_cxx_destructor ||
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 85c768807572f..1b1f6a98988ef 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -397,9 +397,10 @@ pushTemporaryCleanup(CodeGenFunction &CGF, const MaterializeTemporaryExpr *M,
if (const RecordType *RT =
E->getType()->getBaseElementTypeUnsafe()->getAs<RecordType>()) {
// Get the destructor for the reference temporary.
- if (auto *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl());
+ if (auto *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getOriginalDecl());
ClassDecl && !ClassDecl->hasTrivialDestructor())
- ReferenceTemporaryDtor = ClassDecl->getDestructor();
+ ReferenceTemporaryDtor =
+ ClassDecl->getDefinitionOrSelf()->getDestructor();
}
if (!ReferenceTemporaryDtor)
@@ -1198,9 +1199,10 @@ llvm::Value *CodeGenFunction::GetCountedByFieldExprGEP(
return nullptr;
Indices.push_back(Builder.getInt32(0));
- return Builder.CreateInBoundsGEP(
- ConvertType(QualType(RD->getTypeForDecl(), 0)), Res,
- RecIndicesTy(llvm::reverse(Indices)), "counted_by.gep");
+ CanQualType T = CGM.getContext().getCanonicalTagType(RD);
+ return Builder.CreateInBoundsGEP(ConvertType(T), Res,
+ RecIndicesTy(llvm::reverse(Indices)),
+ "counted_by.gep");
}
/// This method is typically called in contexts where we can't generate
@@ -1748,9 +1750,11 @@ static bool isConstantEmittableObjectType(QualType type) {
// Otherwise, all object types satisfy this except C++ classes with
// mutable subobjects or non-trivial copy/destroy behavior.
if (const auto *RT = dyn_cast<RecordType>(type))
- if (const auto *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()))
+ if (const auto *RD = dyn_cast<CXXRecordDecl>(RT->getOriginalDecl())) {
+ RD = RD->getDefinitionOrSelf();
if (RD->hasMutableFields() || !RD->isTrivial())
return false;
+ }
return true;
}
@@ -1911,8 +1915,10 @@ static bool getRangeForType(CodeGenFunction &CGF, QualType Ty,
llvm::APInt &Min, llvm::APInt &End,
bool StrictEnums, bool IsBool) {
const EnumType *ET = Ty->getAs<EnumType>();
- bool IsRegularCPlusPlusEnum = CGF.getLangOpts().CPlusPlus && StrictEnums &&
- ET && !ET->getDecl()->isFixed();
+ const EnumDecl *ED =
+ ET ? ET->getOriginalDecl()->getDefinitionOrSelf() : nullptr;
+ bool IsRegularCPlusPlusEnum =
+ CGF.getLangOpts().CPlusPlus && StrictEnums && ET && !ED->isFixed();
if (!IsBool && !IsRegularCPlusPlusEnum)
return false;
@@ -1920,7 +1926,6 @@ static bool getRangeForType(CodeGenFunction &CGF, QualType Ty,
Min = llvm::APInt(CGF.getContext().getTypeSize(Ty), 0);
End = llvm::APInt(CGF.getContext().getTypeSize(Ty), 2);
} else {
- const EnumDecl *ED = ET->getDecl();
ED->getValueRange(End, Min);
}
return true;
@@ -4266,7 +4271,9 @@ static bool IsPreserveAIArrayBase(CodeGenFunction &CGF, const Expr *ArrayBase) {
const auto *PointeeT = PtrT->getPointeeType()
->getUnqualifiedDesugaredType();
if (const auto *RecT = dyn_cast<RecordType>(PointeeT))
- return RecT->getDecl()->hasAttr<BPFPreserveAccessIndexAttr>();
+ return RecT->getOriginalDecl()
+ ->getMostRecentDecl()
+ ->hasAttr<BPFPreserveAccessIndexAttr>();
return false;
}
@@ -5032,10 +5039,12 @@ LValue CodeGenFunction::EmitLValueForLambdaField(const FieldDecl *Field,
Address Base = GetAddressOfBaseClass(
LambdaLV.getAddress(), ThisTy, BasePathArray.begin(),
BasePathArray.end(), /*NullCheckValue=*/false, SourceLocation());
- LambdaLV = MakeAddrLValue(Base, QualType{LambdaTy->getTypeForDecl(), 0});
+ CanQualType T = getContext().getCanonicalTagType(LambdaTy);
+ LambdaLV = MakeAddrLValue(Base, T);
}
} else {
- QualType LambdaTagType = getContext().getTagDeclType(Field->getParent());
+ CanQualType LambdaTagType =
+ getContext().getCanonicalTagType(Field->getParent());
LambdaLV = MakeNaturalAlignAddrLValue(ThisValue, LambdaTagType);
}
return EmitLValueForField(LambdaLV, Field);
@@ -5160,7 +5169,7 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, const FieldDecl *field,
}
} else {
llvm::DIType *DbgInfo = getDebugInfo()->getOrCreateRecordType(
- getContext().getRecordType(rec), rec->getLocation());
+ getContext().getCanonicalTagType(rec), rec->getLocation());
Addr = Builder.CreatePreserveStructAccessIndex(
Addr, Idx, getDebugInfoFIndex(rec, field->getFieldIndex()),
DbgInfo);
@@ -5622,7 +5631,9 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
case CK_DerivedToBase: {
const auto *DerivedClassTy =
E->getSubExpr()->getType()->castAs<RecordType>();
- auto *DerivedClassDecl = cast<CXXRecordDecl>(DerivedClassTy->getDecl());
+ auto *DerivedClassDecl =
+ cast<CXXRecordDecl>(DerivedClassTy->getOriginalDecl())
+ ->getDefinitionOrSelf();
LValue LV = EmitLValue(E->getSubExpr());
Address This = LV.getAddress();
@@ -5642,7 +5653,9 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
return EmitAggExprToLValue(E);
case CK_BaseToDerived: {
const auto *DerivedClassTy = E->getType()->castAs<RecordType>();
- auto *DerivedClassDecl = cast<CXXRecordDecl>(DerivedClassTy->getDecl());
+ auto *DerivedClassDecl =
+ cast<CXXRecordDecl>(DerivedClassTy->getOriginalDecl())
+ ->getDefinitionOrSelf();
LValue LV = EmitLValue(E->getSubExpr());
@@ -6700,7 +6713,7 @@ void CodeGenFunction::FlattenAccessAndType(
WorkList.emplace_back(CAT->getElementType(), IdxListCopy);
}
} else if (const auto *RT = dyn_cast<RecordType>(T)) {
- const RecordDecl *Record = RT->getDecl();
+ const RecordDecl *Record = RT->getOriginalDecl()->getDefinitionOrSelf();
assert(!Record->isUnion() && "Union types not supported in flat cast.");
const CXXRecordDecl *CXXD = dyn_cast<CXXRecordDecl>(Record);
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index cad6731173700..2c1081d665231 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -272,7 +272,7 @@ bool AggExprEmitter::TypeRequiresGCollection(QualType T) {
if (!RecordTy) return false;
// Don't mess with non-trivial C++ types.
- RecordDecl *Record = RecordTy->getDecl();
+ RecordDecl *Record = RecordTy->getOriginalDecl()->getDefinitionOrSelf();
if (isa<CXXRecordDecl>(Record) &&
(cast<CXXRecordDecl>(Record)->hasNonTrivialCopyConstructor() ||
!cast<CXXRecordDecl>(Record)->hasTrivialDestructor()))
@@ -428,7 +428,10 @@ AggExprEmitter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) {
Ctx.getAsConstantArrayType(E->getSubExpr()->getType());
assert(ArrayType && "std::initializer_list constructed from non-array");
- 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() &&
Ctx.hasSameType(Field->getType()->getPointeeType(),
@@ -1810,7 +1813,10 @@ void AggExprEmitter::VisitCXXParenListOrInitListExpr(
// the disadvantage is that the generated code is more difficult for
// the optimizer, especially with bitfields.
unsigned NumInitElements = InitExprs.size();
- RecordDecl *record = ExprToVisit->getType()->castAs<RecordType>()->getDecl();
+ RecordDecl *record = ExprToVisit->getType()
+ ->castAs<RecordType>()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf();
// We'll need to enter cleanup scopes in case any of the element
// initializers throws an exception.
@@ -2120,7 +2126,7 @@ static CharUnits GetNumNonZeroBytesInInit(const Expr *E, CodeGenFunction &CGF) {
// referencee. InitListExprs for unions and arrays can't have references.
if (const RecordType *RT = E->getType()->getAs<RecordType>()) {
if (!RT->isUnionType()) {
- RecordDecl *SD = RT->getDecl();
+ RecordDecl *SD = RT->getOriginalDecl()->getDefinitionOrSelf();
CharUnits NumNonZeroBytes = CharUnits::Zero();
unsigned ILEElement = 0;
@@ -2172,7 +2178,7 @@ static void CheckAggExprForMemSetUse(AggValueSlot &Slot, const Expr *E,
if (CGF.getLangOpts().CPlusPlus)
if (const RecordType *RT = CGF.getContext()
.getBaseElementType(E->getType())->getAs<RecordType>()) {
- const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getOriginalDecl());
if (RD->hasUserDeclaredConstructor())
return;
}
@@ -2293,7 +2299,8 @@ void CodeGenFunction::EmitAggregateCopy(LValue Dest, LValue Src, QualType Ty,
if (getLangOpts().CPlusPlus) {
if (const RecordType *RT = Ty->getAs<RecordType>()) {
- CXXRecordDecl *Record = cast<CXXRecordDecl>(RT->getDecl());
+ auto *Record =
+ cast<CXXRecordDecl>(RT->getOriginalDecl())->getDefinitionOrSelf();
assert((Record->hasTrivialCopyConstructor() ||
Record->hasTrivialCopyAssignment() ||
Record->hasTrivialMoveConstructor() ||
@@ -2377,7 +2384,7 @@ void CodeGenFunction::EmitAggregateCopy(LValue Dest, LValue Src, QualType Ty,
if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
// fall through
} else if (const RecordType *RecordTy = Ty->getAs<RecordType>()) {
- RecordDecl *Record = RecordTy->getDecl();
+ RecordDecl *Record = RecordTy->getOriginalDecl()->getDefinitionOrSelf();
if (Record->hasObjectMember()) {
CGM.getObjCRuntime().EmitGCMemmoveCollectable(*this, DestPtr, SrcPtr,
SizeVal);
@@ -2386,7 +2393,9 @@ void CodeGenFunction::EmitAggregateCopy(LValue Dest, LValue Src, QualType Ty,
} else if (Ty->isArrayType()) {
QualType BaseType = getContext().getBaseElementType(Ty);
if (const RecordType *RecordTy = BaseType->getAs<RecordType>()) {
- if (RecordTy->getDecl()->hasObjectMember()) {
+ if (RecordTy->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->hasObjectMember()) {
CGM.getObjCRuntime().EmitGCMemmoveCollectable(*this, DestPtr, SrcPtr,
SizeVal);
return;
diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp
index 359e30cb8f5cd..a92b89def6433 100644
--- a/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/clang/lib/CodeGen/CGExprCXX.cpp
@@ -181,7 +181,7 @@ static CXXRecordDecl *getCXXRecord(const Expr *E) {
if (const PointerType *PTy = T->getAs<PointerType>())
T = PTy->getPointeeType();
const RecordType *Ty = T->castAs<RecordType>();
- return cast<CXXRecordDecl>(Ty->getDecl());
+ return cast<CXXRecordDecl>(Ty->getOriginalDecl())->getDefinitionOrSelf();
}
// Note: This function also emit constructor calls to support a MSVC
@@ -206,7 +206,7 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
}
bool HasQualifier = ME->hasQualifier();
- NestedNameSpecifier *Qualifier = HasQualifier ? ME->getQualifier() : nullptr;
+ NestedNameSpecifier Qualifier = ME->getQualifier();
bool IsArrow = ME->isArrow();
const Expr *Base = ME->getBase();
@@ -217,7 +217,7 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
const CallExpr *CE, const CXXMethodDecl *MD, ReturnValueSlot ReturnValue,
- bool HasQualifier, NestedNameSpecifier *Qualifier, bool IsArrow,
+ bool HasQualifier, NestedNameSpecifier Qualifier, bool IsArrow,
const Expr *Base, llvm::CallBase **CallOrInvoke) {
assert(isa<CXXMemberCallExpr>(CE) || isa<CXXOperatorCallExpr>(CE));
@@ -361,7 +361,7 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
if (sanitizePerformTypeCheck())
EmitTypeCheck(CodeGenFunction::TCK_MemberCall, CallLoc,
This.emitRawPointer(*this),
- C.getRecordType(CalleeDecl->getParent()),
+ C.getCanonicalTagType(CalleeDecl->getParent()),
/*Alignment=*/CharUnits::Zero(), SkippedChecks);
// C++ [class.virtual]p12:
@@ -461,9 +461,9 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E,
else
This = EmitLValue(BaseExpr, KnownNonNull).getAddress();
- EmitTypeCheck(
- TCK_MemberCall, E->getExprLoc(), This.emitRawPointer(*this),
- QualType(MPT->getMostRecentCXXRecordDecl()->getTypeForDecl(), 0));
+ CanQualType ClassType = CGM.getContext().getCanonicalTagType(RD);
+ EmitTypeCheck(TCK_MemberCall, E->getExprLoc(), This.emitRawPointer(*this),
+ ClassType);
// Get the member function pointer.
llvm::Value *MemFnPtr = EmitScalarExpr(MemFnExpr);
@@ -476,8 +476,7 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E,
CallArgList Args;
- QualType ThisType =
- getContext().getPointerType(getContext().getTagDeclType(RD));
+ QualType ThisType = getContext().getPointerType(ClassType);
// Push the this ptr.
Args.add(RValue::get(ThisPtrForCall), ThisType);
@@ -498,7 +497,7 @@ RValue CodeGenFunction::EmitCXXOperatorMemberCallExpr(
assert(MD->isImplicitObjectMemberFunction() &&
"Trying to emit a member call expr on a static method!");
return EmitCXXMemberOrOperatorMemberCallExpr(
- E, MD, ReturnValue, /*HasQualifier=*/false, /*Qualifier=*/nullptr,
+ E, MD, ReturnValue, /*HasQualifier=*/false, /*Qualifier=*/std::nullopt,
/*IsArrow=*/false, E->getArg(0), CallOrInvoke);
}
@@ -1237,11 +1236,12 @@ void CodeGenFunction::EmitNewArrayInitializer(
// usually use memset.
if (auto *ILE = dyn_cast<InitListExpr>(Init)) {
if (const RecordType *RType = ILE->getType()->getAs<RecordType>()) {
- if (RType->getDecl()->isStruct()) {
+ const RecordDecl *RD = RType->getOriginalDecl()->getDefinitionOrSelf();
+ if (RD->isStruct()) {
unsigned NumElements = 0;
- if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RType->getDecl()))
+ if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RD))
NumElements = CXXRD->getNumBases();
- for (auto *Field : RType->getDecl()->fields())
+ for (auto *Field : RD->fields())
if (!Field->isUnnamedBitField())
++NumElements;
// FIXME: Recurse into nested InitListExprs.
@@ -1687,9 +1687,11 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
QualType AlignValT = sizeType;
if (allocatorType->getNumParams() > IndexOfAlignArg) {
AlignValT = allocatorType->getParamType(IndexOfAlignArg);
- assert(getContext().hasSameUnqualifiedType(
- AlignValT->castAs<EnumType>()->getDecl()->getIntegerType(),
- sizeType) &&
+ assert(getContext().hasSameUnqualifiedType(AlignValT->castAs<EnumType>()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->getIntegerType(),
+ sizeType) &&
"wrong type for alignment parameter");
++ParamsToSkip;
} else {
@@ -1972,7 +1974,8 @@ static bool EmitObjectDelete(CodeGenFunction &CGF,
// destructor is virtual, we'll just emit the vcall and return.
const CXXDestructorDecl *Dtor = nullptr;
if (const RecordType *RT = ElementType->getAs<RecordType>()) {
- CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ auto *RD =
+ cast<CXXRecordDecl>(RT->getOriginalDecl())->getDefinitionOrSelf();
if (RD->hasDefinition() && !RD->hasTrivialDestructor()) {
Dtor = RD->getDestructor();
diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp
index 715bd392f59f7..a96c1518d2a1d 100644
--- a/clang/lib/CodeGen/CGExprConstant.cpp
+++ b/clang/lib/CodeGen/CGExprConstant.cpp
@@ -714,7 +714,10 @@ static bool EmitDesignatedInitUpdater(ConstantEmitter &Emitter,
}
bool ConstStructBuilder::Build(const InitListExpr *ILE, bool AllowOverwrite) {
- RecordDecl *RD = ILE->getType()->castAs<RecordType>()->getDecl();
+ RecordDecl *RD = ILE->getType()
+ ->castAs<RecordType>()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf();
const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
unsigned FieldNo = -1;
@@ -977,7 +980,8 @@ bool ConstStructBuilder::DoZeroInitPadding(const ASTRecordLayout &Layout,
llvm::Constant *ConstStructBuilder::Finalize(QualType Type) {
Type = Type.getNonReferenceType();
- RecordDecl *RD = Type->castAs<RecordType>()->getDecl();
+ RecordDecl *RD =
+ Type->castAs<RecordType>()->getOriginalDecl()->getDefinitionOrSelf();
llvm::Type *ValTy = CGM.getTypes().ConvertType(Type);
return Builder.build(ValTy, RD->hasFlexibleArrayMember());
}
@@ -1000,7 +1004,8 @@ llvm::Constant *ConstStructBuilder::BuildStruct(ConstantEmitter &Emitter,
ConstantAggregateBuilder Const(Emitter.CGM);
ConstStructBuilder Builder(Emitter, Const, CharUnits::Zero());
- const RecordDecl *RD = ValTy->castAs<RecordType>()->getDecl();
+ const RecordDecl *RD =
+ ValTy->castAs<RecordType>()->getOriginalDecl()->getDefinitionOrSelf();
const CXXRecordDecl *CD = dyn_cast<CXXRecordDecl>(RD);
if (!Builder.Build(Val, RD, false, CD, CharUnits::Zero()))
return nullptr;
@@ -1506,7 +1511,9 @@ class ConstExprEmitter
llvm::Type *ValTy = CGM.getTypes().ConvertType(destType);
bool HasFlexibleArray = false;
if (const auto *RT = destType->getAs<RecordType>())
- HasFlexibleArray = RT->getDecl()->hasFlexibleArrayMember();
+ HasFlexibleArray = RT->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->hasFlexibleArrayMember();
return Const.build(ValTy, HasFlexibleArray);
}
@@ -2640,7 +2647,9 @@ static llvm::Constant *EmitNullConstant(CodeGenModule &CGM,
}
const CXXRecordDecl *base =
- cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl());
+ cast<CXXRecordDecl>(
+ I.getType()->castAs<RecordType>()->getOriginalDecl())
+ ->getDefinitionOrSelf();
// Ignore empty bases.
if (isEmptyRecordForLayout(CGM.getContext(), I.getType()) ||
@@ -2679,8 +2688,10 @@ static llvm::Constant *EmitNullConstant(CodeGenModule &CGM,
// Fill in the virtual bases, if we're working with the complete object.
if (CXXR && asCompleteObject) {
for (const auto &I : CXXR->vbases()) {
- const CXXRecordDecl *base =
- cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl());
+ const auto *base =
+ cast<CXXRecordDecl>(
+ I.getType()->castAs<RecordType>()->getOriginalDecl())
+ ->getDefinitionOrSelf();
// Ignore empty bases.
if (isEmptyRecordForLayout(CGM.getContext(), I.getType()))
@@ -2746,7 +2757,9 @@ llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) {
}
if (const RecordType *RT = T->getAs<RecordType>())
- return ::EmitNullConstant(*this, RT->getDecl(), /*complete object*/ true);
+ return ::EmitNullConstant(*this,
+ RT->getOriginalDecl()->getDefinitionOrSelf(),
+ /*complete object*/ true);
assert(T->isMemberDataPointerType() &&
"Should only see pointers to data members here!");
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index 44931d0481e26..0318f85a344d7 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -3515,7 +3515,9 @@ Value *ScalarExprEmitter::VisitOffsetOfExpr(OffsetOfExpr *E) {
case OffsetOfNode::Field: {
FieldDecl *MemberDecl = ON.getField();
- RecordDecl *RD = CurrentType->castAs<RecordType>()->getDecl();
+ RecordDecl *RD = CurrentType->castAs<RecordType>()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf();
const ASTRecordLayout &RL = CGF.getContext().getASTRecordLayout(RD);
// Compute the index of the field in its parent.
@@ -3548,15 +3550,16 @@ Value *ScalarExprEmitter::VisitOffsetOfExpr(OffsetOfExpr *E) {
continue;
}
- RecordDecl *RD = CurrentType->castAs<RecordType>()->getDecl();
- const ASTRecordLayout &RL = CGF.getContext().getASTRecordLayout(RD);
+ const ASTRecordLayout &RL = CGF.getContext().getASTRecordLayout(
+ CurrentType->castAs<RecordType>()->getOriginalDecl());
// Save the element type.
CurrentType = ON.getBase()->getType();
// Compute the offset to the base.
auto *BaseRT = CurrentType->castAs<RecordType>();
- auto *BaseRD = cast<CXXRecordDecl>(BaseRT->getDecl());
+ auto *BaseRD =
+ cast<CXXRecordDecl>(BaseRT->getOriginalDecl())->getDefinitionOrSelf();
CharUnits OffsetInt = RL.getBaseClassOffset(BaseRD);
Offset = llvm::ConstantInt::get(ResultType, OffsetInt.getQuantity());
break;
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index c1fd6f22f693b..ad7048b61e727 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -186,8 +186,7 @@ static const clang::HLSLAttributedResourceType *
createBufferHandleType(const HLSLBufferDecl *BufDecl) {
ASTContext &AST = BufDecl->getASTContext();
QualType QT = AST.getHLSLAttributedResourceType(
- AST.HLSLResourceTy,
- QualType(BufDecl->getLayoutStruct()->getTypeForDecl(), 0),
+ AST.HLSLResourceTy, AST.getCanonicalTagType(BufDecl->getLayoutStruct()),
HLSLAttributedResourceType::Attributes(ResourceClass::CBuffer));
return cast<HLSLAttributedResourceType>(QT.getTypePtr());
}
diff --git a/clang/lib/CodeGen/CGNonTrivialStruct.cpp b/clang/lib/CodeGen/CGNonTrivialStruct.cpp
index e0983ef256e71..1b941fff8b644 100644
--- a/clang/lib/CodeGen/CGNonTrivialStruct.cpp
+++ b/clang/lib/CodeGen/CGNonTrivialStruct.cpp
@@ -39,7 +39,8 @@ template <class Derived> struct StructVisitor {
template <class... Ts>
void visitStructFields(QualType QT, CharUnits CurStructOffset, Ts... Args) {
- const RecordDecl *RD = QT->castAs<RecordType>()->getDecl();
+ const RecordDecl *RD =
+ QT->castAs<RecordType>()->getOriginalDecl()->getDefinitionOrSelf();
// Iterate over the fields of the struct.
for (const FieldDecl *FD : RD->fields()) {
@@ -464,7 +465,8 @@ template <class Derived> struct GenFuncBase {
if (WrongType) {
std::string FuncName = std::string(F->getName());
- SourceLocation Loc = QT->castAs<RecordType>()->getDecl()->getLocation();
+ SourceLocation Loc =
+ QT->castAs<RecordType>()->getOriginalDecl()->getLocation();
CGM.Error(Loc, "special function " + FuncName +
" for non-trivial C struct has incorrect type");
return nullptr;
@@ -560,7 +562,8 @@ struct GenBinaryFunc : CopyStructVisitor<Derived, IsMove>,
if (FD->isZeroLengthBitField())
return;
- QualType RT = QualType(FD->getParent()->getTypeForDecl(), 0);
+ CanQualType RT =
+ this->CGF->getContext().getCanonicalTagType(FD->getParent());
llvm::Type *Ty = this->CGF->ConvertType(RT);
Address DstAddr = this->getAddrWithOffset(Addrs[DstIdx], Offset);
LValue DstBase =
diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp
index 6f87444d3f672..04b6d4fe29296 100644
--- a/clang/lib/CodeGen/CGObjC.cpp
+++ b/clang/lib/CodeGen/CGObjC.cpp
@@ -1000,7 +1000,9 @@ PropertyImplStrategy::PropertyImplStrategy(CodeGenModule &CGM,
// Compute whether the ivar has strong members.
if (CGM.getLangOpts().getGC())
if (const RecordType *recordType = ivarType->getAs<RecordType>())
- HasStrong = recordType->getDecl()->hasObjectMember();
+ HasStrong = recordType->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->hasObjectMember();
// We can never access structs with object members with a native
// access, because we need to use write barriers. This is what
diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp
index a52c92cdbc83b..adb5639e7289c 100644
--- a/clang/lib/CodeGen/CGObjCMac.cpp
+++ b/clang/lib/CodeGen/CGObjCMac.cpp
@@ -2493,7 +2493,7 @@ void CGObjCCommonMac::BuildRCBlockVarRecordLayout(const RecordType *RT,
CharUnits BytePos,
bool &HasUnion,
bool ByrefLayout) {
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
SmallVector<const FieldDecl *, 16> Fields(RD->fields());
llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
const llvm::StructLayout *RecLayout =
@@ -3352,7 +3352,8 @@ static bool hasWeakMember(QualType type) {
}
if (auto recType = type->getAs<RecordType>()) {
- for (auto *field : recType->getDecl()->fields()) {
+ for (auto *field :
+ recType->getOriginalDecl()->getDefinitionOrSelf()->fields()) {
if (hasWeakMember(field->getType()))
return true;
}
@@ -5174,7 +5175,7 @@ CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
}
void IvarLayoutBuilder::visitRecord(const RecordType *RT, CharUnits offset) {
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
// If this is a union, remember that we had one, because it might mess
// up the ordering of layout entries.
@@ -5660,7 +5661,7 @@ ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
nullptr, false, ICIS_NoInit));
RD->completeDefinition();
- SuperCTy = Ctx.getTagDeclType(RD);
+ SuperCTy = Ctx.getCanonicalTagType(RD);
SuperPtrCTy = Ctx.getPointerType(SuperCTy);
SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
@@ -6006,7 +6007,7 @@ ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(
false, ICIS_NoInit));
RD->completeDefinition();
- MessageRefCTy = Ctx.getTagDeclType(RD);
+ MessageRefCTy = Ctx.getCanonicalTagType(RD);
MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));
diff --git a/clang/lib/CodeGen/CGObjCRuntime.cpp b/clang/lib/CodeGen/CGObjCRuntime.cpp
index 6e2f32022a01e..cbf99534d2ce6 100644
--- a/clang/lib/CodeGen/CGObjCRuntime.cpp
+++ b/clang/lib/CodeGen/CGObjCRuntime.cpp
@@ -440,7 +440,9 @@ void CGObjCRuntime::destroyCalleeDestroyedArguments(CodeGenFunction &CGF,
} else {
QualType QT = param->getType();
auto *RT = QT->getAs<RecordType>();
- if (RT && RT->getDecl()->isParamDestroyedInCallee()) {
+ if (RT && RT->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->isParamDestroyedInCallee()) {
RValue RV = I->getRValue(CGF);
QualType::DestructionKind DtorKind = QT.isDestructedType();
switch (DtorKind) {
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index a5f2f0efa2c3b..503c02f02cc6c 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -2915,7 +2915,7 @@ createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind,
addFieldToRecordDecl(C, UD, KmpInt32Ty);
addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy);
UD->completeDefinition();
- QualType KmpCmplrdataTy = C.getRecordType(UD);
+ CanQualType KmpCmplrdataTy = C.getCanonicalTagType(UD);
RecordDecl *RD = C.buildImplicitRecord("kmp_task_t");
RD->startDefinition();
addFieldToRecordDecl(C, RD, C.VoidPtrTy);
@@ -2950,7 +2950,7 @@ createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy,
RD->startDefinition();
addFieldToRecordDecl(C, RD, KmpTaskTQTy);
if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates))
- addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD));
+ addFieldToRecordDecl(C, RD, C.getCanonicalTagType(PrivateRD));
RD->completeDefinition();
return RD;
}
@@ -3582,7 +3582,7 @@ static void getKmpAffinityType(ASTContext &C, QualType &KmpTaskAffinityInfoTy) {
addFieldToRecordDecl(C, KmpAffinityInfoRD, C.getSizeType());
addFieldToRecordDecl(C, KmpAffinityInfoRD, FlagsTy);
KmpAffinityInfoRD->completeDefinition();
- KmpTaskAffinityInfoTy = C.getRecordType(KmpAffinityInfoRD);
+ KmpTaskAffinityInfoTy = C.getCanonicalTagType(KmpAffinityInfoRD);
}
}
@@ -3640,7 +3640,7 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
// Build type kmp_task_t (if not built yet).
if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) {
if (SavedKmpTaskloopTQTy.isNull()) {
- SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl(
+ SavedKmpTaskloopTQTy = C.getCanonicalTagType(createKmpTaskTRecordDecl(
CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy));
}
KmpTaskTQTy = SavedKmpTaskloopTQTy;
@@ -3650,7 +3650,7 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) &&
"Expected taskloop, task or target directive");
if (SavedKmpTaskTQTy.isNull()) {
- SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl(
+ SavedKmpTaskTQTy = C.getCanonicalTagType(createKmpTaskTRecordDecl(
CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy));
}
KmpTaskTQTy = SavedKmpTaskTQTy;
@@ -3659,7 +3659,8 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
// Build particular struct kmp_task_t for the given task.
const RecordDecl *KmpTaskTWithPrivatesQTyRD =
createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates);
- QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD);
+ CanQualType KmpTaskTWithPrivatesQTy =
+ C.getCanonicalTagType(KmpTaskTWithPrivatesQTyRD);
QualType KmpTaskTWithPrivatesPtrQTy =
C.getPointerType(KmpTaskTWithPrivatesQTy);
llvm::Type *KmpTaskTWithPrivatesPtrTy = CGF.Builder.getPtrTy(0);
@@ -3914,7 +3915,10 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
// Fill the data in the resulting kmp_task_t record.
// Copy shareds if there are any.
Address KmpTaskSharedsPtr = Address::invalid();
- if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) {
+ if (!SharedsTy->getAsStructureType()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->field_empty()) {
KmpTaskSharedsPtr = Address(
CGF.EmitLoadOfScalar(
CGF.EmitLValueForField(
@@ -3944,8 +3948,11 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
enum { Priority = 0, Destructors = 1 };
// Provide pointer to function with destructors for privates.
auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1);
- const RecordDecl *KmpCmplrdataUD =
- (*FI)->getType()->getAsUnionType()->getDecl();
+ const RecordDecl *KmpCmplrdataUD = (*FI)
+ ->getType()
+ ->getAsUnionType()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf();
if (NeedsCleanup) {
llvm::Value *DestructorFn = emitDestructorsFunction(
CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
@@ -4015,7 +4022,7 @@ static void getDependTypes(ASTContext &C, QualType &KmpDependInfoTy,
addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType());
addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy);
KmpDependInfoRD->completeDefinition();
- KmpDependInfoTy = C.getRecordType(KmpDependInfoRD);
+ KmpDependInfoTy = C.getCanonicalTagType(KmpDependInfoRD);
}
}
@@ -5714,7 +5721,7 @@ llvm::Value *CGOpenMPRuntime::emitTaskReductionInit(
const FieldDecl *FlagsFD = addFieldToRecordDecl(
C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false));
RD->completeDefinition();
- QualType RDType = C.getRecordType(RD);
+ CanQualType RDType = C.getCanonicalTagType(RD);
unsigned Size = Data.ReductionVars.size();
llvm::APInt ArraySize(/*numBits=*/64, Size);
QualType ArrayRDType =
@@ -10640,7 +10647,7 @@ static unsigned evaluateCDTSize(const FunctionDecl *FD,
unsigned Offset = 0;
if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
if (ParamAttrs[Offset].Kind == Vector)
- CDT = C.getPointerType(C.getRecordType(MD->getParent()));
+ CDT = C.getPointerType(C.getCanonicalTagType(MD->getParent()));
++Offset;
}
if (CDT.isNull()) {
@@ -11222,7 +11229,7 @@ void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF,
addFieldToRecordDecl(C, RD, Int64Ty);
addFieldToRecordDecl(C, RD, Int64Ty);
RD->completeDefinition();
- KmpDimTy = C.getRecordType(RD);
+ KmpDimTy = C.getCanonicalTagType(RD);
} else {
RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl());
}
@@ -11718,7 +11725,7 @@ Address CGOpenMPRuntime::emitLastprivateConditionalInit(CodeGenFunction &CGF,
VDField = addFieldToRecordDecl(C, RD, VD->getType().getNonReferenceType());
FiredField = addFieldToRecordDecl(C, RD, C.CharTy);
RD->completeDefinition();
- NewType = C.getRecordType(RD);
+ NewType = C.getCanonicalTagType(RD);
Address Addr = CGF.CreateMemTemp(NewType, C.getDeclAlign(VD), VD->getName());
BaseLVal = CGF.MakeAddrLValue(Addr, NewType, AlignmentSource::Decl);
I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal);
diff --git a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp
index e25b6948d30f8..0e746ddfe13a2 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp
@@ -769,7 +769,7 @@ void CGOpenMPRuntimeGPU::emitKernelDeinit(CodeGenFunction &CGF,
"_openmp_teams_reduction_type_$_", RecordDecl::TagKind::Union);
StaticRD->startDefinition();
for (const RecordDecl *TeamReductionRec : TeamsReductions) {
- QualType RecTy = C.getRecordType(TeamReductionRec);
+ CanQualType RecTy = C.getCanonicalTagType(TeamReductionRec);
auto *Field = FieldDecl::Create(
C, StaticRD, SourceLocation(), SourceLocation(), nullptr, RecTy,
C.getTrivialTypeSourceInfo(RecTy, SourceLocation()),
@@ -779,7 +779,7 @@ void CGOpenMPRuntimeGPU::emitKernelDeinit(CodeGenFunction &CGF,
StaticRD->addDecl(Field);
}
StaticRD->completeDefinition();
- QualType StaticTy = C.getRecordType(StaticRD);
+ CanQualType StaticTy = C.getCanonicalTagType(StaticRD);
llvm::Type *LLVMReductionsBufferTy =
CGM.getTypes().ConvertTypeForMem(StaticTy);
const auto &DL = CGM.getModule().getDataLayout();
diff --git a/clang/lib/CodeGen/CGPointerAuth.cpp b/clang/lib/CodeGen/CGPointerAuth.cpp
index dcef01a5eb6d3..1a5ffb5eb33f8 100644
--- a/clang/lib/CodeGen/CGPointerAuth.cpp
+++ b/clang/lib/CodeGen/CGPointerAuth.cpp
@@ -531,7 +531,7 @@ llvm::Constant *CodeGenModule::getMemberFunctionPointer(llvm::Constant *Pointer,
llvm::Constant *CodeGenModule::getMemberFunctionPointer(const FunctionDecl *FD,
llvm::Type *Ty) {
QualType FT = FD->getType();
- FT = getContext().getMemberPointerType(FT, /*Qualifier=*/nullptr,
+ FT = getContext().getMemberPointerType(FT, /*Qualifier=*/std::nullopt,
cast<CXXMethodDecl>(FD)->getParent());
return getMemberFunctionPointer(getRawFunctionPointer(FD, Ty), FT);
}
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index e0650067b9547..28d518a52cfe7 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -3270,7 +3270,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
LValue CodeGenFunction::InitCapturedStruct(const CapturedStmt &S) {
const RecordDecl *RD = S.getCapturedRecordDecl();
- QualType RecordTy = getContext().getRecordType(RD);
+ CanQualType RecordTy = getContext().getCanonicalTagType(RD);
// Initialize the captured struct.
LValue SlotLV =
@@ -3350,7 +3350,7 @@ CodeGenFunction::GenerateCapturedStmtFunction(const CapturedStmt &S) {
// Initialize variable-length arrays.
LValue Base = MakeNaturalAlignRawAddrLValue(
- CapturedStmtInfo->getContextValue(), Ctx.getTagDeclType(RD));
+ CapturedStmtInfo->getContextValue(), Ctx.getCanonicalTagType(RD));
for (auto *FD : RD->fields()) {
if (FD->hasCapturedVLAType()) {
auto *ExprArg =
diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index 5822e0f6db89a..f6a0ca574a191 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -5273,7 +5273,8 @@ void CodeGenFunction::EmitOMPTargetTaskBasedDirective(
// Emit outlined function for task construct.
const CapturedStmt *CS = S.getCapturedStmt(OMPD_task);
Address CapturedStruct = GenerateCapturedStmtArgument(*CS);
- QualType SharedsTy = getContext().getRecordType(CS->getCapturedRecordDecl());
+ CanQualType SharedsTy =
+ getContext().getCanonicalTagType(CS->getCapturedRecordDecl());
auto I = CS->getCapturedDecl()->param_begin();
auto PartId = std::next(I);
auto TaskT = std::next(I, 4);
@@ -5507,7 +5508,8 @@ void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &S) {
// Emit outlined function for task construct.
const CapturedStmt *CS = S.getCapturedStmt(OMPD_task);
Address CapturedStruct = GenerateCapturedStmtArgument(*CS);
- QualType SharedsTy = getContext().getRecordType(CS->getCapturedRecordDecl());
+ CanQualType SharedsTy =
+ getContext().getCanonicalTagType(CS->getCapturedRecordDecl());
const Expr *IfCond = nullptr;
for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
if (C->getNameModifier() == OMPD_unknown ||
@@ -7890,7 +7892,8 @@ void CodeGenFunction::EmitOMPTaskLoopBasedDirective(const OMPLoopDirective &S) {
OMPLexicalScope Scope(*this, S, OMPD_taskloop, /*EmitPreInitStmt=*/false);
CapturedStruct = GenerateCapturedStmtArgument(*CS);
}
- QualType SharedsTy = getContext().getRecordType(CS->getCapturedRecordDecl());
+ CanQualType SharedsTy =
+ getContext().getCanonicalTagType(CS->getCapturedRecordDecl());
const Expr *IfCond = nullptr;
for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
if (C->getNameModifier() == OMPD_unknown ||
diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp
index 0b6e830e0d557..e14e883a55ac5 100644
--- a/clang/lib/CodeGen/CGVTables.cpp
+++ b/clang/lib/CodeGen/CGVTables.cpp
@@ -971,7 +971,7 @@ llvm::GlobalVariable *CodeGenVTables::GenerateConstructionVTable(
VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
llvm::Constant *RTTI = CGM.GetAddrOfRTTIDescriptor(
- CGM.getContext().getTagDeclType(Base.getBase()));
+ CGM.getContext().getCanonicalTagType(Base.getBase()));
// Create and set the initializer.
ConstantInitBuilder builder(CGM);
@@ -1382,8 +1382,8 @@ void CodeGenModule::EmitVTableTypeMetadata(const CXXRecordDecl *RD,
AP.second.AddressPointIndex,
{}};
llvm::raw_string_ostream Stream(N.TypeName);
- getCXXABI().getMangleContext().mangleCanonicalTypeName(
- QualType(N.Base->getTypeForDecl(), 0), Stream);
+ CanQualType T = getContext().getCanonicalTagType(N.Base);
+ getCXXABI().getMangleContext().mangleCanonicalTypeName(T, Stream);
AddressPoints.push_back(std::move(N));
}
@@ -1404,7 +1404,7 @@ void CodeGenModule::EmitVTableTypeMetadata(const CXXRecordDecl *RD,
continue;
llvm::Metadata *MD = CreateMetadataIdentifierForVirtualMemPtrType(
Context.getMemberPointerType(Comps[I].getFunctionDecl()->getType(),
- /*Qualifier=*/nullptr, AP.Base));
+ /*Qualifier=*/std::nullopt, AP.Base));
VTable->addTypeMetadata((ComponentWidth * I).getQuantity(), MD);
}
}
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 776a646ceb32f..3307e3fbd2196 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -2224,7 +2224,9 @@ CodeGenFunction::EmitNullInitialization(Address DestPtr, QualType Ty) {
// Ignore empty classes in C++.
if (getLangOpts().CPlusPlus) {
if (const RecordType *RT = Ty->getAs<RecordType>()) {
- if (cast<CXXRecordDecl>(RT->getDecl())->isEmpty())
+ if (cast<CXXRecordDecl>(RT->getOriginalDecl())
+ ->getDefinitionOrSelf()
+ ->isEmpty())
return;
}
}
@@ -2494,10 +2496,6 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) {
case Type::HLSLInlineSpirv:
llvm_unreachable("type class is never variably-modified!");
- case Type::Elaborated:
- type = cast<ElaboratedType>(ty)->getNamedType();
- break;
-
case Type::Adjusted:
type = cast<AdjustedType>(ty)->getAdjustedType();
break;
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 6c32c98cec011..c33c215c03e01 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -2974,7 +2974,7 @@ class CodeGenFunction : public CodeGenTypeCache {
/// member.
bool hasVolatileMember(QualType T) {
if (const RecordType *RT = T->getAs<RecordType>()) {
- const RecordDecl *RD = cast<RecordDecl>(RT->getDecl());
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
return RD->hasVolatileMember();
}
return false;
@@ -4560,7 +4560,7 @@ class CodeGenFunction : public CodeGenTypeCache {
ArrayRef<llvm::Value *> args);
CGCallee BuildAppleKextVirtualCall(const CXXMethodDecl *MD,
- NestedNameSpecifier *Qual, llvm::Type *Ty);
+ NestedNameSpecifier Qual, llvm::Type *Ty);
CGCallee BuildAppleKextVirtualDestructorCall(const CXXDestructorDecl *DD,
CXXDtorType Type,
@@ -4665,7 +4665,7 @@ class CodeGenFunction : public CodeGenTypeCache {
llvm::CallBase **CallOrInvoke = nullptr);
RValue EmitCXXMemberOrOperatorMemberCallExpr(
const CallExpr *CE, const CXXMethodDecl *MD, ReturnValueSlot ReturnValue,
- bool HasQualifier, NestedNameSpecifier *Qualifier, bool IsArrow,
+ bool HasQualifier, NestedNameSpecifier Qualifier, bool IsArrow,
const Expr *Base, llvm::CallBase **CallOrInvoke);
// Compute the object pointer.
Address EmitCXXMemberDataPointerAddress(
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index c8866f15745c2..6fdb187b3a242 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -2795,7 +2795,7 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
for (const CXXRecordDecl *Base : getMostBaseClasses(MD->getParent())) {
llvm::Metadata *Id =
CreateMetadataIdentifierForType(Context.getMemberPointerType(
- MD->getType(), /*Qualifier=*/nullptr, Base));
+ MD->getType(), /*Qualifier=*/std::nullopt, Base));
F->addTypeMetadata(0, Id);
}
}
@@ -4154,9 +4154,11 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
// Check if T is a class type with a destructor that's not dllimport.
static bool HasNonDllImportDtor(QualType T) {
if (const auto *RT = T->getBaseElementTypeUnsafe()->getAs<RecordType>())
- if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()))
+ if (auto *RD = dyn_cast<CXXRecordDecl>(RT->getOriginalDecl())) {
+ RD = RD->getDefinitionOrSelf();
if (RD->getDestructor() && !RD->getDestructor()->hasAttr<DLLImportAttr>())
return true;
+ }
return false;
}
@@ -6030,7 +6032,7 @@ static bool isVarDeclStrongDefinition(const ASTContext &Context,
return true;
if (const auto *RT = VarType->getAs<RecordType>()) {
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
for (const FieldDecl *FD : RD->fields()) {
if (FD->isBitField())
continue;
@@ -6737,7 +6739,7 @@ QualType CodeGenModule::getObjCFastEnumerationStateType() {
}
D->completeDefinition();
- ObjCFastEnumerationStateType = Context.getTagDeclType(D);
+ ObjCFastEnumerationStateType = Context.getCanonicalTagType(D);
}
return ObjCFastEnumerationStateType;
@@ -7247,7 +7249,8 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
CXXRecordDecl *CRD = cast<CXXRecordDecl>(D);
if (CGDebugInfo *DI = getModuleDebugInfo()) {
if (CRD->hasDefinition())
- DI->EmitAndRetainType(getContext().getRecordType(cast<RecordDecl>(D)));
+ DI->EmitAndRetainType(
+ getContext().getCanonicalTagType(cast<RecordDecl>(D)));
if (auto *ES = D->getASTContext().getExternalSource())
if (ES->hasExternalDefinitions(D) == ExternalASTSource::EK_Never)
DI->completeUnusedClass(*CRD);
@@ -7466,20 +7469,23 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
case Decl::Typedef:
case Decl::TypeAlias: // using foo = bar; [C++11]
if (CGDebugInfo *DI = getModuleDebugInfo())
- DI->EmitAndRetainType(
- getContext().getTypedefType(cast<TypedefNameDecl>(D)));
+ DI->EmitAndRetainType(getContext().getTypedefType(
+ ElaboratedTypeKeyword::None, /*Qualifier=*/std::nullopt,
+ cast<TypedefNameDecl>(D)));
break;
case Decl::Record:
if (CGDebugInfo *DI = getModuleDebugInfo())
if (cast<RecordDecl>(D)->getDefinition())
- DI->EmitAndRetainType(getContext().getRecordType(cast<RecordDecl>(D)));
+ DI->EmitAndRetainType(
+ getContext().getCanonicalTagType(cast<RecordDecl>(D)));
break;
case Decl::Enum:
if (CGDebugInfo *DI = getModuleDebugInfo())
if (cast<EnumDecl>(D)->getDefinition())
- DI->EmitAndRetainType(getContext().getEnumType(cast<EnumDecl>(D)));
+ DI->EmitAndRetainType(
+ getContext().getCanonicalTagType(cast<EnumDecl>(D)));
break;
case Decl::HLSLBuffer:
@@ -7933,8 +7939,8 @@ bool CodeGenModule::NeedAllVtablesTypeId() const {
void CodeGenModule::AddVTableTypeMetadata(llvm::GlobalVariable *VTable,
CharUnits Offset,
const CXXRecordDecl *RD) {
- llvm::Metadata *MD =
- CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0));
+ CanQualType T = getContext().getCanonicalTagType(RD);
+ llvm::Metadata *MD = CreateMetadataIdentifierForType(T);
VTable->addTypeMetadata(Offset.getQuantity(), MD);
if (CodeGenOpts.SanitizeCfiCrossDso)
diff --git a/clang/lib/CodeGen/CodeGenTBAA.cpp b/clang/lib/CodeGen/CodeGenTBAA.cpp
index a02a009158d12..3dc0859cc5d51 100644
--- a/clang/lib/CodeGen/CodeGenTBAA.cpp
+++ b/clang/lib/CodeGen/CodeGenTBAA.cpp
@@ -143,7 +143,7 @@ static bool TypeHasMayAlias(QualType QTy) {
/// Check if the given type is a valid base type to be used in access tags.
static bool isValidBaseType(QualType QTy) {
if (const RecordType *TTy = QTy->getAs<RecordType>()) {
- const RecordDecl *RD = TTy->getDecl()->getDefinition();
+ const RecordDecl *RD = TTy->getOriginalDecl()->getDefinition();
// Incomplete types are not valid base access types.
if (!RD)
return false;
@@ -311,7 +311,7 @@ llvm::MDNode *CodeGenTBAA::getTypeInfoHelper(const Type *Ty) {
// This also covers anonymous structs and unions, which have a different
// compatibility rule, but it doesn't matter because you can never have a
// pointer to an anonymous struct or union.
- if (!RT->getDecl()->getDeclName())
+ if (!RT->getOriginalDecl()->getDeclName())
return getAnyPtr(PtrDepth);
// For non-builtin types use the mangled name of the canonical type.
@@ -333,14 +333,15 @@ llvm::MDNode *CodeGenTBAA::getTypeInfoHelper(const Type *Ty) {
// Enum types are distinct types. In C++ they have "underlying types",
// however they aren't related for TBAA.
if (const EnumType *ETy = dyn_cast<EnumType>(Ty)) {
+ const EnumDecl *ED = ETy->getOriginalDecl()->getDefinitionOrSelf();
if (!Features.CPlusPlus)
- return getTypeInfo(ETy->getDecl()->getIntegerType());
+ return getTypeInfo(ED->getIntegerType());
// In C++ mode, types have linkage, so we can rely on the ODR and
// on their mangled names, if they're external.
// TODO: Is there a way to get a program-wide unique name for a
// decl with local linkage or no linkage?
- if (!ETy->getDecl()->isExternallyVisible())
+ if (!ED->isExternallyVisible())
return getChar();
SmallString<256> OutName;
@@ -433,7 +434,7 @@ CodeGenTBAA::CollectFields(uint64_t BaseOffset,
llvm::MDBuilder::TBAAStructField(BaseOffset, Size, TBAATag));
return true;
}
- const RecordDecl *RD = TTy->getDecl()->getDefinition();
+ const RecordDecl *RD = TTy->getOriginalDecl()->getDefinition();
if (RD->hasFlexibleArrayMember())
return false;
@@ -514,7 +515,7 @@ CodeGenTBAA::getTBAAStructInfo(QualType QTy) {
llvm::MDNode *CodeGenTBAA::getBaseTypeInfoHelper(const Type *Ty) {
if (auto *TTy = dyn_cast<RecordType>(Ty)) {
- const RecordDecl *RD = TTy->getDecl()->getDefinition();
+ const RecordDecl *RD = TTy->getOriginalDecl()->getDefinition();
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
using TBAAStructField = llvm::MDBuilder::TBAAStructField;
SmallVector<TBAAStructField, 4> Fields;
diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp
index c98503e4bbd26..f2a0a649a88fd 100644
--- a/clang/lib/CodeGen/CodeGenTypes.cpp
+++ b/clang/lib/CodeGen/CodeGenTypes.cpp
@@ -229,12 +229,13 @@ bool CodeGenTypes::isFuncTypeConvertible(const FunctionType *FT) {
/// UpdateCompletedType - When we find the full definition for a TagDecl,
/// replace the 'opaque' type we previously made for it if applicable.
void CodeGenTypes::UpdateCompletedType(const TagDecl *TD) {
+ CanQualType T = CGM.getContext().getCanonicalTagType(TD);
// If this is an enum being completed, then we flush all non-struct types from
// the cache. This allows function types and other things that may be derived
// from the enum to be recomputed.
if (const EnumDecl *ED = dyn_cast<EnumDecl>(TD)) {
// Only flush the cache if we've actually already converted this type.
- if (TypeCache.count(ED->getTypeForDecl())) {
+ if (TypeCache.count(T->getTypePtr())) {
// Okay, we formed some types based on this. We speculated that the enum
// would be lowered to i32, so we only need to flush the cache if this
// didn't happen.
@@ -255,7 +256,7 @@ void CodeGenTypes::UpdateCompletedType(const TagDecl *TD) {
// Only complete it if we converted it already. If we haven't converted it
// yet, we'll just do it lazily.
- if (RecordDeclTypes.count(Context.getTagDeclType(RD).getTypePtr()))
+ if (RecordDeclTypes.count(T.getTypePtr()))
ConvertRecordDeclType(RD);
// If necessary, provide the full definition of a type only used with a
@@ -265,7 +266,7 @@ void CodeGenTypes::UpdateCompletedType(const TagDecl *TD) {
}
void CodeGenTypes::RefreshTypeCacheForClass(const CXXRecordDecl *RD) {
- QualType T = Context.getRecordType(RD);
+ CanQualType T = Context.getCanonicalTagType(RD);
T = Context.getCanonicalType(T);
const Type *Ty = T.getTypePtr();
@@ -311,11 +312,11 @@ llvm::Type *CodeGenTypes::ConvertFunctionTypeInternal(QualType QFT) {
// Force conversion of all the relevant record types, to make sure
// we re-convert the FunctionType when appropriate.
if (const RecordType *RT = FT->getReturnType()->getAs<RecordType>())
- ConvertRecordDeclType(RT->getDecl());
+ ConvertRecordDeclType(RT->getOriginalDecl()->getDefinitionOrSelf());
if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FT))
for (unsigned i = 0, e = FPT->getNumParams(); i != e; i++)
if (const RecordType *RT = FPT->getParamType(i)->getAs<RecordType>())
- ConvertRecordDeclType(RT->getDecl());
+ ConvertRecordDeclType(RT->getOriginalDecl()->getDefinitionOrSelf());
SkippedLayout = true;
@@ -373,7 +374,7 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
// RecordTypes are cached and processed specially.
if (const RecordType *RT = dyn_cast<RecordType>(Ty))
- return ConvertRecordDeclType(RT->getDecl());
+ return ConvertRecordDeclType(RT->getOriginalDecl()->getDefinitionOrSelf());
llvm::Type *CachedType = nullptr;
auto TCI = TypeCache.find(Ty);
@@ -699,7 +700,8 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
break;
case Type::Enum: {
- const EnumDecl *ED = cast<EnumType>(Ty)->getDecl();
+ const EnumDecl *ED =
+ cast<EnumType>(Ty)->getOriginalDecl()->getDefinitionOrSelf();
if (ED->isCompleteDefinition() || ED->isFixed())
return ConvertType(ED->getIntegerType());
// Return a placeholder 'i32' type. This can be changed later when the
@@ -725,8 +727,10 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
case Type::MemberPointer: {
auto *MPTy = cast<MemberPointerType>(Ty);
if (!getCXXABI().isMemberPointerConvertible(MPTy)) {
- auto *C = MPTy->getMostRecentCXXRecordDecl()->getTypeForDecl();
- auto Insertion = RecordsWithOpaqueMemberPointers.try_emplace(C);
+ CanQualType T = CGM.getContext().getCanonicalTagType(
+ MPTy->getMostRecentCXXRecordDecl());
+ auto Insertion =
+ RecordsWithOpaqueMemberPointers.try_emplace(T.getTypePtr());
if (Insertion.second)
Insertion.first->second = llvm::StructType::create(getLLVMContext());
ResultType = Insertion.first->second;
@@ -789,7 +793,7 @@ bool CodeGenModule::isPaddedAtomicType(const AtomicType *type) {
llvm::StructType *CodeGenTypes::ConvertRecordDeclType(const RecordDecl *RD) {
// TagDecl's are not necessarily unique, instead use the (clang)
// type connected to the decl.
- const Type *Key = Context.getTagDeclType(RD).getTypePtr();
+ const Type *Key = Context.getCanonicalTagType(RD).getTypePtr();
llvm::StructType *&Entry = RecordDeclTypes[Key];
@@ -810,7 +814,10 @@ llvm::StructType *CodeGenTypes::ConvertRecordDeclType(const RecordDecl *RD) {
if (const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) {
for (const auto &I : CRD->bases()) {
if (I.isVirtual()) continue;
- ConvertRecordDeclType(I.getType()->castAs<RecordType>()->getDecl());
+ ConvertRecordDeclType(I.getType()
+ ->castAs<RecordType>()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf());
}
}
@@ -830,7 +837,7 @@ llvm::StructType *CodeGenTypes::ConvertRecordDeclType(const RecordDecl *RD) {
/// getCGRecordLayout - Return record layout info for the given record decl.
const CGRecordLayout &
CodeGenTypes::getCGRecordLayout(const RecordDecl *RD) {
- const Type *Key = Context.getTagDeclType(RD).getTypePtr();
+ const Type *Key = Context.getCanonicalTagType(RD).getTypePtr();
auto I = CGRecordLayouts.find(Key);
if (I != CGRecordLayouts.end())
@@ -869,7 +876,7 @@ bool CodeGenTypes::isZeroInitializable(QualType T) {
// Records are non-zero-initializable if they contain any
// non-zero-initializable subobjects.
if (const RecordType *RT = T->getAs<RecordType>()) {
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
return isZeroInitializable(RD);
}
diff --git a/clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp b/clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp
index 1ed33894b15aa..ac56dda74abb7 100644
--- a/clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp
+++ b/clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp
@@ -101,7 +101,8 @@ llvm::TargetExtType *HLSLBufferLayoutBuilder::createLayoutType(
const RecordType *RT = RecordTypes.back();
RecordTypes.pop_back();
- for (const auto *FD : RT->getDecl()->fields()) {
+ for (const auto *FD :
+ RT->getOriginalDecl()->getDefinitionOrSelf()->fields()) {
assert((!PackOffsets || Index < PackOffsets->size()) &&
"number of elements in layout struct does not match number of "
"packoffset annotations");
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index f4a99467010af..f0f7b97c624f7 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -826,7 +826,7 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
for (const CXXRecordDecl *Base : CGM.getMostBaseClasses(RD)) {
llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(
getContext().getMemberPointerType(MPT->getPointeeType(),
- /*Qualifier=*/nullptr,
+ /*Qualifier=*/std::nullopt,
Base->getCanonicalDecl()));
llvm::Value *TypeId =
llvm::MetadataAsValue::get(CGF.getLLVMContext(), MD);
@@ -1236,7 +1236,7 @@ llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const APValue &MP,
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MPD)) {
llvm::Constant *Src = BuildMemberPointer(MD, ThisAdjustment);
QualType SrcType = getContext().getMemberPointerType(
- MD->getType(), /*Qualifier=*/nullptr, MD->getParent());
+ MD->getType(), /*Qualifier=*/std::nullopt, MD->getParent());
return pointerAuthResignMemberFunctionPointer(Src, MPType, SrcType, CGM);
}
@@ -1392,8 +1392,9 @@ void ItaniumCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF,
// to pass to the deallocation function.
// Grab the vtable pointer as an intptr_t*.
- auto *ClassDecl =
- cast<CXXRecordDecl>(ElementType->castAs<RecordType>()->getDecl());
+ auto *ClassDecl = cast<CXXRecordDecl>(
+ ElementType->castAs<RecordType>()->getOriginalDecl())
+ ->getDefinitionOrSelf();
llvm::Value *VTable = CGF.GetVTablePtr(Ptr, CGF.UnqualPtrTy, ClassDecl);
// Track back to entry -2 and pull out the offset there.
@@ -1479,7 +1480,8 @@ void ItaniumCXXABI::emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) {
// trivial destructor (or isn't a record), we just pass null.
llvm::Constant *Dtor = nullptr;
if (const RecordType *RecordTy = ThrowType->getAs<RecordType>()) {
- CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordTy->getDecl());
+ CXXRecordDecl *Record =
+ cast<CXXRecordDecl>(RecordTy->getOriginalDecl())->getDefinitionOrSelf();
if (!Record->hasTrivialDestructor()) {
// __cxa_throw is declared to take its destructor as void (*)(void *). We
// must match that if function pointers can be authenticated with a
@@ -1606,7 +1608,8 @@ llvm::Value *ItaniumCXXABI::EmitTypeid(CodeGenFunction &CGF,
Address ThisPtr,
llvm::Type *StdTypeInfoPtrTy) {
auto *ClassDecl =
- cast<CXXRecordDecl>(SrcRecordTy->castAs<RecordType>()->getDecl());
+ cast<CXXRecordDecl>(SrcRecordTy->castAs<RecordType>()->getOriginalDecl())
+ ->getDefinitionOrSelf();
llvm::Value *Value = CGF.GetVTablePtr(ThisPtr, CGM.GlobalsInt8PtrTy,
ClassDecl);
@@ -1763,7 +1766,8 @@ llvm::Value *ItaniumCXXABI::emitDynamicCastToVoid(CodeGenFunction &CGF,
Address ThisAddr,
QualType SrcRecordTy) {
auto *ClassDecl =
- cast<CXXRecordDecl>(SrcRecordTy->castAs<RecordType>()->getDecl());
+ cast<CXXRecordDecl>(SrcRecordTy->castAs<RecordType>()->getOriginalDecl())
+ ->getDefinitionOrSelf();
llvm::Value *OffsetToTop;
if (CGM.getItaniumVTableContext().isRelativeLayout()) {
// Get the vtable pointer.
@@ -2016,7 +2020,7 @@ void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
const VTableLayout &VTLayout = VTContext.getVTableLayout(RD);
llvm::GlobalVariable::LinkageTypes Linkage = CGM.getVTableLinkage(RD);
llvm::Constant *RTTI =
- CGM.GetAddrOfRTTIDescriptor(CGM.getContext().getTagDeclType(RD));
+ CGM.GetAddrOfRTTIDescriptor(CGM.getContext().getCanonicalTagType(RD));
// Create and set the initializer.
ConstantInitBuilder builder(CGM);
@@ -3755,7 +3759,8 @@ static bool ShouldUseExternalRTTIDescriptor(CodeGenModule &CGM,
if (!Context.getLangOpts().RTTI) return false;
if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
- const CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
+ const CXXRecordDecl *RD =
+ cast<CXXRecordDecl>(RecordTy->getOriginalDecl())->getDefinitionOrSelf();
if (!RD->hasDefinition())
return false;
@@ -3789,7 +3794,9 @@ static bool ShouldUseExternalRTTIDescriptor(CodeGenModule &CGM,
/// IsIncompleteClassType - Returns whether the given record type is incomplete.
static bool IsIncompleteClassType(const RecordType *RecordTy) {
- return !RecordTy->getDecl()->isCompleteDefinition();
+ return !RecordTy->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->isCompleteDefinition();
}
/// ContainsIncompleteClassType - Returns whether the given type contains an
@@ -3815,9 +3822,7 @@ static bool ContainsIncompleteClassType(QualType Ty) {
if (const MemberPointerType *MemberPointerTy =
dyn_cast<MemberPointerType>(Ty)) {
// Check if the class type is incomplete.
- const auto *ClassType = cast<RecordType>(
- MemberPointerTy->getMostRecentCXXRecordDecl()->getTypeForDecl());
- if (IsIncompleteClassType(ClassType))
+ if (!MemberPointerTy->getMostRecentCXXRecordDecl()->hasDefinition())
return true;
return ContainsIncompleteClassType(MemberPointerTy->getPointeeType());
@@ -3846,8 +3851,9 @@ static bool CanUseSingleInheritance(const CXXRecordDecl *RD) {
return false;
// Check that the class is dynamic iff the base is.
- auto *BaseDecl =
- cast<CXXRecordDecl>(Base->getType()->castAs<RecordType>()->getDecl());
+ auto *BaseDecl = cast<CXXRecordDecl>(
+ Base->getType()->castAs<RecordType>()->getOriginalDecl())
+ ->getDefinitionOrSelf();
if (!BaseDecl->isEmpty() &&
BaseDecl->isDynamicClass() != RD->isDynamicClass())
return false;
@@ -3926,7 +3932,8 @@ void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty,
case Type::Record: {
const CXXRecordDecl *RD =
- cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl());
+ cast<CXXRecordDecl>(cast<RecordType>(Ty)->getOriginalDecl())
+ ->getDefinitionOrSelf();
if (!RD->hasDefinition() || !RD->getNumBases()) {
VTableName = ClassTypeInfo;
@@ -4048,7 +4055,8 @@ static llvm::GlobalVariable::LinkageTypes getTypeInfoLinkage(CodeGenModule &CGM,
return llvm::GlobalValue::LinkOnceODRLinkage;
if (const RecordType *Record = dyn_cast<RecordType>(Ty)) {
- const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
+ const CXXRecordDecl *RD =
+ cast<CXXRecordDecl>(Record->getOriginalDecl())->getDefinitionOrSelf();
if (RD->hasAttr<WeakAttr>())
return llvm::GlobalValue::WeakODRLinkage;
if (CGM.getTriple().isWindowsItaniumEnvironment())
@@ -4212,7 +4220,8 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(
case Type::Record: {
const CXXRecordDecl *RD =
- cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl());
+ cast<CXXRecordDecl>(cast<RecordType>(Ty)->getOriginalDecl())
+ ->getDefinitionOrSelf();
if (!RD->hasDefinition() || !RD->getNumBases()) {
// We don't need to emit any fields.
break;
@@ -4259,7 +4268,8 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(
if (CGM.getTarget().hasPS4DLLImportExport() &&
GVDLLStorageClass != llvm::GlobalVariable::DLLExportStorageClass) {
if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
- const CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getOriginalDecl())
+ ->getDefinitionOrSelf();
if (RD->hasAttr<DLLExportAttr>() ||
CXXRecordNonInlineHasAttr<DLLExportAttr>(RD))
GVDLLStorageClass = llvm::GlobalVariable::DLLExportStorageClass;
@@ -4363,8 +4373,9 @@ static unsigned ComputeVMIClassTypeInfoFlags(const CXXBaseSpecifier *Base,
unsigned Flags = 0;
- auto *BaseDecl =
- cast<CXXRecordDecl>(Base->getType()->castAs<RecordType>()->getDecl());
+ auto *BaseDecl = cast<CXXRecordDecl>(
+ Base->getType()->castAs<RecordType>()->getOriginalDecl())
+ ->getDefinitionOrSelf();
if (Base->isVirtual()) {
// Mark the virtual base as seen.
@@ -4464,7 +4475,9 @@ void ItaniumRTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) {
Fields.push_back(ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(Base.getType()));
auto *BaseDecl =
- cast<CXXRecordDecl>(Base.getType()->castAs<RecordType>()->getDecl());
+ cast<CXXRecordDecl>(
+ Base.getType()->castAs<RecordType>()->getOriginalDecl())
+ ->getDefinitionOrSelf();
int64_t OffsetFlags = 0;
@@ -4554,9 +4567,8 @@ ItaniumRTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) {
// attributes of the type pointed to.
unsigned Flags = extractPBaseFlags(CGM.getContext(), PointeeTy);
- const auto *ClassType =
- cast<RecordType>(Ty->getMostRecentCXXRecordDecl()->getTypeForDecl());
- if (IsIncompleteClassType(ClassType))
+ const auto *RD = Ty->getMostRecentCXXRecordDecl();
+ if (!RD->hasDefinition())
Flags |= PTI_ContainingClassIncomplete;
llvm::Type *UnsignedIntLTy =
@@ -4574,8 +4586,8 @@ ItaniumRTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) {
// __context is a pointer to an abi::__class_type_info corresponding to the
// class type containing the member pointed to
// (e.g., the "A" in "int A::*").
- Fields.push_back(
- ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(QualType(ClassType, 0)));
+ CanQualType T = CGM.getContext().getCanonicalTagType(RD);
+ Fields.push_back(ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(T));
}
llvm::Constant *ItaniumCXXABI::getAddrOfRTTIDescriptor(QualType Ty) {
@@ -5155,7 +5167,7 @@ ItaniumCXXABI::getSignedVirtualMemberFunctionPointer(const CXXMethodDecl *MD) {
.getDecl());
llvm::Constant *thunk = getOrCreateVirtualFunctionPointerThunk(origMD);
QualType funcType = CGM.getContext().getMemberPointerType(
- MD->getType(), /*Qualifier=*/nullptr, MD->getParent());
+ MD->getType(), /*Qualifier=*/std::nullopt, MD->getParent());
return CGM.getMemberFunctionPointer(thunk, funcType);
}
diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index a181559834296..977c9a27a6ad6 100644
--- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -870,7 +870,8 @@ MicrosoftCXXABI::getRecordArgABI(const CXXRecordDecl *RD) const {
// it indirectly. Prior to MSVC version 19.14, passing overaligned
// arguments was not supported and resulted in a compiler error. In 19.14
// and later versions, such arguments are now passed indirectly.
- TypeInfo Info = getContext().getTypeInfo(RD->getTypeForDecl());
+ TypeInfo Info =
+ getContext().getTypeInfo(getContext().getCanonicalTagType(RD));
if (Info.isAlignRequired() && Info.Align > 4)
return RAA_Indirect;
@@ -2918,15 +2919,15 @@ llvm::Constant *MicrosoftCXXABI::EmitMemberPointer(const APValue &MP,
if (!FD)
FD = cast<FieldDecl>(*cast<IndirectFieldDecl>(MPD)->chain_begin());
const CXXRecordDecl *RD = cast<CXXRecordDecl>(FD->getParent());
- RD = RD->getMostRecentNonInjectedDecl();
+ RD = RD->getMostRecentDecl();
C = EmitMemberDataPointer(RD, FieldOffset);
}
if (!MemberPointerPath.empty()) {
const CXXRecordDecl *SrcRD = cast<CXXRecordDecl>(MPD->getDeclContext());
const MemberPointerType *SrcTy =
- Ctx.getMemberPointerType(DstTy->getPointeeType(), /*Qualifier=*/nullptr,
- SrcRD)
+ Ctx.getMemberPointerType(DstTy->getPointeeType(),
+ /*Qualifier=*/std::nullopt, SrcRD)
->castAs<MemberPointerType>();
bool DerivedMember = MP.isMemberPointerToDerivedMember();
@@ -2963,7 +2964,7 @@ MicrosoftCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) {
assert(MD->isInstance() && "Member function must not be static!");
CharUnits NonVirtualBaseAdjustment = CharUnits::Zero();
- const CXXRecordDecl *RD = MD->getParent()->getMostRecentNonInjectedDecl();
+ const CXXRecordDecl *RD = MD->getParent()->getMostRecentDecl();
CodeGenTypes &Types = CGM.getTypes();
unsigned VBTableIndex = 0;
@@ -3684,7 +3685,7 @@ struct MSRTTIBuilder {
MSRTTIBuilder(MicrosoftCXXABI &ABI, const CXXRecordDecl *RD)
: CGM(ABI.CGM), Context(CGM.getContext()),
VMContext(CGM.getLLVMContext()), Module(CGM.getModule()), RD(RD),
- Linkage(getLinkageForRTTI(CGM.getContext().getTagDeclType(RD))),
+ Linkage(getLinkageForRTTI(CGM.getContext().getCanonicalTagType(RD))),
ABI(ABI) {}
llvm::GlobalVariable *getBaseClassDescriptor(const MSRTTIClass &Classes);
@@ -3858,7 +3859,7 @@ MSRTTIBuilder::getBaseClassDescriptor(const MSRTTIClass &Class) {
// Initialize the BaseClassDescriptor.
llvm::Constant *Fields[] = {
ABI.getImageRelativeConstant(
- ABI.getAddrOfRTTIDescriptor(Context.getTypeDeclType(Class.RD))),
+ ABI.getAddrOfRTTIDescriptor(Context.getCanonicalTagType(Class.RD))),
llvm::ConstantInt::get(CGM.IntTy, Class.NumBases),
llvm::ConstantInt::get(CGM.IntTy, Class.OffsetInVBase),
llvm::ConstantInt::get(CGM.IntTy, VBPtrOffset),
@@ -3905,7 +3906,7 @@ MSRTTIBuilder::getCompleteObjectLocator(const VPtrInfo &Info) {
llvm::ConstantInt::get(CGM.IntTy, OffsetToTop),
llvm::ConstantInt::get(CGM.IntTy, VFPtrOffset),
ABI.getImageRelativeConstant(
- CGM.GetAddrOfRTTIDescriptor(Context.getTypeDeclType(RD))),
+ CGM.GetAddrOfRTTIDescriptor(Context.getCanonicalTagType(RD))),
ABI.getImageRelativeConstant(getClassHierarchyDescriptor()),
ABI.getImageRelativeConstant(COL),
};
@@ -4076,7 +4077,7 @@ MicrosoftCXXABI::getAddrOfCXXCtorClosure(const CXXConstructorDecl *CD,
const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeMSCtorClosure(CD, CT);
llvm::FunctionType *ThunkTy = CGM.getTypes().GetFunctionType(FnInfo);
const CXXRecordDecl *RD = CD->getParent();
- QualType RecordTy = getContext().getRecordType(RD);
+ CanQualType RecordTy = getContext().getCanonicalTagType(RD);
llvm::Function *ThunkFn = llvm::Function::Create(
ThunkTy, getLinkageForRTTI(RecordTy), ThunkName.str(), &CGM.getModule());
ThunkFn->setCallingConv(static_cast<llvm::CallingConv::ID>(
@@ -4312,7 +4313,7 @@ llvm::GlobalVariable *MicrosoftCXXABI::getCatchableTypeArray(QualType T) {
// Turn our record back into a pointer if the exception object is a
// pointer.
- QualType RTTITy = QualType(Class.RD->getTypeForDecl(), 0);
+ CanQualType RTTITy = Context.getCanonicalTagType(Class.RD);
if (IsPointer)
RTTITy = Context.getPointerType(RTTITy);
CatchableTypes.insert(getCatchableType(RTTITy, Class.OffsetInVBase,
@@ -4463,8 +4464,8 @@ void MicrosoftCXXABI::emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) {
std::pair<llvm::Value *, const CXXRecordDecl *>
MicrosoftCXXABI::LoadVTablePtr(CodeGenFunction &CGF, Address This,
const CXXRecordDecl *RD) {
- std::tie(This, std::ignore, RD) =
- performBaseAdjustment(CGF, This, QualType(RD->getTypeForDecl(), 0));
+ CanQualType T = CGF.getContext().getCanonicalTagType(RD);
+ std::tie(This, std::ignore, RD) = performBaseAdjustment(CGF, This, T);
return {CGF.GetVTablePtr(This, CGM.Int8PtrTy, RD), RD};
}
diff --git a/clang/lib/CodeGen/SwiftCallingConv.cpp b/clang/lib/CodeGen/SwiftCallingConv.cpp
index 10f9f20bca313..de58e0d95a866 100644
--- a/clang/lib/CodeGen/SwiftCallingConv.cpp
+++ b/clang/lib/CodeGen/SwiftCallingConv.cpp
@@ -66,9 +66,9 @@ void SwiftAggLowering::addTypedData(QualType type, CharUnits begin) {
// Record types.
if (auto recType = type->getAs<RecordType>()) {
- addTypedData(recType->getDecl(), begin);
+ addTypedData(recType->getOriginalDecl(), begin);
- // Array types.
+ // Array types.
} else if (type->isArrayType()) {
// Incomplete array types (flexible array members?) don't provide
// data to lay out, and the other cases shouldn't be possible.
@@ -814,7 +814,7 @@ static ABIArgInfo classifyType(CodeGenModule &CGM, CanQualType type,
bool forReturn) {
unsigned IndirectAS = CGM.getDataLayout().getAllocaAddrSpace();
if (auto recordType = dyn_cast<RecordType>(type)) {
- auto record = recordType->getDecl();
+ auto record = recordType->getOriginalDecl();
auto &layout = CGM.getContext().getASTRecordLayout(record);
if (mustPassRecordIndirectly(CGM, record))
@@ -822,7 +822,8 @@ static ABIArgInfo classifyType(CodeGenModule &CGM, CanQualType type,
/*AddrSpace=*/IndirectAS, /*byval=*/false);
SwiftAggLowering lowering(CGM);
- lowering.addTypedData(recordType->getDecl(), CharUnits::Zero(), layout);
+ lowering.addTypedData(recordType->getOriginalDecl(), CharUnits::Zero(),
+ layout);
lowering.finish();
return classifyExpandedType(lowering, forReturn, layout.getAlignment(),
diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp
index b82c46966cf0b..289f8a9dcf211 100644
--- a/clang/lib/CodeGen/Targets/AArch64.cpp
+++ b/clang/lib/CodeGen/Targets/AArch64.cpp
@@ -375,7 +375,7 @@ ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty, bool IsVariadicFn,
if (!passAsAggregateType(Ty)) {
// Treat an enum type as its underlying type.
if (const EnumType *EnumTy = Ty->getAs<EnumType>())
- Ty = EnumTy->getDecl()->getIntegerType();
+ Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
if (const auto *EIT = Ty->getAs<BitIntType>())
if (EIT->getNumBits() > 128)
@@ -496,7 +496,7 @@ ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty, bool IsVariadicFn,
const RecordType *RT = Ty->getAs<RecordType>();
if (!RT)
return false;
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
for (const auto &I : CXXRD->bases())
if (!Self(Self, I.getType()))
@@ -548,7 +548,8 @@ ABIArgInfo AArch64ABIInfo::classifyReturnType(QualType RetTy,
if (!passAsAggregateType(RetTy)) {
// Treat an enum type as its underlying type.
if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
- RetTy = EnumTy->getDecl()->getIntegerType();
+ RetTy =
+ EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
if (const auto *EIT = RetTy->getAs<BitIntType>())
if (EIT->getNumBits() > 128)
@@ -744,7 +745,7 @@ bool AArch64ABIInfo::passAsPureScalableType(
return false;
// Pure scalable types are never unions and never contain unions.
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
if (RD->isUnion())
return false;
diff --git a/clang/lib/CodeGen/Targets/AMDGPU.cpp b/clang/lib/CodeGen/Targets/AMDGPU.cpp
index 47a552a7bf495..41bccbb5721b2 100644
--- a/clang/lib/CodeGen/Targets/AMDGPU.cpp
+++ b/clang/lib/CodeGen/Targets/AMDGPU.cpp
@@ -96,7 +96,7 @@ unsigned AMDGPUABIInfo::numRegsForType(QualType Ty) const {
}
if (const RecordType *RT = Ty->getAs<RecordType>()) {
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
assert(!RD->hasFlexibleArrayMember());
for (const FieldDecl *Field : RD->fields()) {
@@ -153,7 +153,7 @@ ABIArgInfo AMDGPUABIInfo::classifyReturnType(QualType RetTy) const {
return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0)));
if (const RecordType *RT = RetTy->getAs<RecordType>()) {
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
if (RD->hasFlexibleArrayMember())
return DefaultABIInfo::classifyReturnType(RetTy);
}
@@ -246,7 +246,7 @@ ABIArgInfo AMDGPUABIInfo::classifyArgumentType(QualType Ty, bool Variadic,
return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0)));
if (const RecordType *RT = Ty->getAs<RecordType>()) {
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
if (RD->hasFlexibleArrayMember())
return DefaultABIInfo::classifyArgumentType(Ty);
}
diff --git a/clang/lib/CodeGen/Targets/ARC.cpp b/clang/lib/CodeGen/Targets/ARC.cpp
index c8db7e8f9706e..ace524e1976d9 100644
--- a/clang/lib/CodeGen/Targets/ARC.cpp
+++ b/clang/lib/CodeGen/Targets/ARC.cpp
@@ -106,13 +106,14 @@ ABIArgInfo ARCABIInfo::classifyArgumentType(QualType Ty,
// Treat an enum type as its underlying type.
if (const EnumType *EnumTy = Ty->getAs<EnumType>())
- Ty = EnumTy->getDecl()->getIntegerType();
+ Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
auto SizeInRegs = llvm::alignTo(getContext().getTypeSize(Ty), 32) / 32;
if (isAggregateTypeForABI(Ty)) {
// Structures with flexible arrays are always indirect.
- if (RT && RT->getDecl()->hasFlexibleArrayMember())
+ if (RT &&
+ RT->getOriginalDecl()->getDefinitionOrSelf()->hasFlexibleArrayMember())
return getIndirectByValue(Ty);
// Ignore empty structs/unions.
diff --git a/clang/lib/CodeGen/Targets/ARM.cpp b/clang/lib/CodeGen/Targets/ARM.cpp
index 68f9e01856486..532ba4cead244 100644
--- a/clang/lib/CodeGen/Targets/ARM.cpp
+++ b/clang/lib/CodeGen/Targets/ARM.cpp
@@ -383,7 +383,7 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty, bool isVariadic,
if (!isAggregateTypeForABI(Ty)) {
// Treat an enum type as its underlying type.
if (const EnumType *EnumTy = Ty->getAs<EnumType>()) {
- Ty = EnumTy->getDecl()->getIntegerType();
+ Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
}
if (const auto *EIT = Ty->getAs<BitIntType>())
@@ -516,7 +516,7 @@ static bool isIntegerLikeType(QualType Ty, ASTContext &Context,
if (!RT) return false;
// Ignore records with flexible arrays.
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
if (RD->hasFlexibleArrayMember())
return false;
@@ -593,7 +593,8 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy, bool isVariadic,
if (!isAggregateTypeForABI(RetTy)) {
// Treat an enum type as its underlying type.
if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
- RetTy = EnumTy->getDecl()->getIntegerType();
+ RetTy =
+ EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
if (const auto *EIT = RetTy->getAs<BitIntType>())
if (EIT->getNumBits() > 64)
@@ -718,7 +719,7 @@ bool ARMABIInfo::containsAnyFP16Vectors(QualType Ty) const {
return false;
return containsAnyFP16Vectors(AT->getElementType());
} else if (const RecordType *RT = Ty->getAs<RecordType>()) {
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
// If this is a C++ record, check the bases first.
if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))
diff --git a/clang/lib/CodeGen/Targets/BPF.cpp b/clang/lib/CodeGen/Targets/BPF.cpp
index 880a891083c3a..87d50e671d251 100644
--- a/clang/lib/CodeGen/Targets/BPF.cpp
+++ b/clang/lib/CodeGen/Targets/BPF.cpp
@@ -48,7 +48,7 @@ class BPFABIInfo : public DefaultABIInfo {
}
if (const EnumType *EnumTy = Ty->getAs<EnumType>())
- Ty = EnumTy->getDecl()->getIntegerType();
+ Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
ASTContext &Context = getContext();
if (const auto *EIT = Ty->getAs<BitIntType>())
@@ -70,7 +70,8 @@ class BPFABIInfo : public DefaultABIInfo {
// Treat an enum type as its underlying type.
if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
- RetTy = EnumTy->getDecl()->getIntegerType();
+ RetTy =
+ EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
ASTContext &Context = getContext();
if (const auto *EIT = RetTy->getAs<BitIntType>())
diff --git a/clang/lib/CodeGen/Targets/CSKY.cpp b/clang/lib/CodeGen/Targets/CSKY.cpp
index ef26d483a180a..7e5a16f30727f 100644
--- a/clang/lib/CodeGen/Targets/CSKY.cpp
+++ b/clang/lib/CodeGen/Targets/CSKY.cpp
@@ -116,7 +116,7 @@ ABIArgInfo CSKYABIInfo::classifyArgumentType(QualType Ty, int &ArgGPRsLeft,
if (!isAggregateTypeForABI(Ty)) {
// Treat an enum type as its underlying type.
if (const EnumType *EnumTy = Ty->getAs<EnumType>())
- Ty = EnumTy->getDecl()->getIntegerType();
+ Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
// All integral types are promoted to XLen width, unless passed on the
// stack.
diff --git a/clang/lib/CodeGen/Targets/Hexagon.cpp b/clang/lib/CodeGen/Targets/Hexagon.cpp
index 2976657360650..0c423429eda4f 100644
--- a/clang/lib/CodeGen/Targets/Hexagon.cpp
+++ b/clang/lib/CodeGen/Targets/Hexagon.cpp
@@ -98,7 +98,7 @@ ABIArgInfo HexagonABIInfo::classifyArgumentType(QualType Ty,
if (!isAggregateTypeForABI(Ty)) {
// Treat an enum type as its underlying type.
if (const EnumType *EnumTy = Ty->getAs<EnumType>())
- Ty = EnumTy->getDecl()->getIntegerType();
+ Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
uint64_t Size = getContext().getTypeSize(Ty);
if (Size <= 64)
@@ -161,7 +161,8 @@ ABIArgInfo HexagonABIInfo::classifyReturnType(QualType RetTy) const {
if (!isAggregateTypeForABI(RetTy)) {
// Treat an enum type as its underlying type.
if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
- RetTy = EnumTy->getDecl()->getIntegerType();
+ RetTy =
+ EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
if (Size > 64 && RetTy->isBitIntType())
return getNaturalAlignIndirect(
diff --git a/clang/lib/CodeGen/Targets/Lanai.cpp b/clang/lib/CodeGen/Targets/Lanai.cpp
index 6f75bd54a8ef2..08cb36034f6fd 100644
--- a/clang/lib/CodeGen/Targets/Lanai.cpp
+++ b/clang/lib/CodeGen/Targets/Lanai.cpp
@@ -102,7 +102,8 @@ ABIArgInfo LanaiABIInfo::classifyArgumentType(QualType Ty,
if (isAggregateTypeForABI(Ty)) {
// Structures with flexible arrays are always indirect.
- if (RT && RT->getDecl()->hasFlexibleArrayMember())
+ if (RT &&
+ RT->getOriginalDecl()->getDefinitionOrSelf()->hasFlexibleArrayMember())
return getIndirectResult(Ty, /*ByVal=*/true, State);
// Ignore empty structs/unions.
@@ -125,7 +126,7 @@ ABIArgInfo LanaiABIInfo::classifyArgumentType(QualType Ty,
// Treat an enum type as its underlying type.
if (const auto *EnumTy = Ty->getAs<EnumType>())
- Ty = EnumTy->getDecl()->getIntegerType();
+ Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
bool InReg = shouldUseInReg(Ty, State);
diff --git a/clang/lib/CodeGen/Targets/LoongArch.cpp b/clang/lib/CodeGen/Targets/LoongArch.cpp
index 7640f3779816a..af863e6101e2c 100644
--- a/clang/lib/CodeGen/Targets/LoongArch.cpp
+++ b/clang/lib/CodeGen/Targets/LoongArch.cpp
@@ -150,7 +150,7 @@ bool LoongArchABIInfo::detectFARsEligibleStructHelper(
// Non-zero-length arrays of empty records make the struct ineligible to be
// passed via FARs in C++.
if (const auto *RTy = EltTy->getAs<RecordType>()) {
- if (ArraySize != 0 && isa<CXXRecordDecl>(RTy->getDecl()) &&
+ if (ArraySize != 0 && isa<CXXRecordDecl>(RTy->getOriginalDecl()) &&
isEmptyRecord(getContext(), EltTy, true, true))
return false;
}
@@ -169,7 +169,7 @@ bool LoongArchABIInfo::detectFARsEligibleStructHelper(
// copy constructor are not eligible for the FP calling convention.
if (getRecordArgABI(Ty, CGT.getCXXABI()))
return false;
- const RecordDecl *RD = RTy->getDecl();
+ const RecordDecl *RD = RTy->getOriginalDecl()->getDefinitionOrSelf();
if (isEmptyRecord(getContext(), Ty, true, true) &&
(!RD->isUnion() || !isa<CXXRecordDecl>(RD)))
return true;
@@ -181,7 +181,9 @@ bool LoongArchABIInfo::detectFARsEligibleStructHelper(
if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
for (const CXXBaseSpecifier &B : CXXRD->bases()) {
const auto *BDecl =
- cast<CXXRecordDecl>(B.getType()->castAs<RecordType>()->getDecl());
+ cast<CXXRecordDecl>(
+ B.getType()->castAs<RecordType>()->getOriginalDecl())
+ ->getDefinitionOrSelf();
if (!detectFARsEligibleStructHelper(
B.getType(), CurOff + Layout.getBaseClassOffset(BDecl),
Field1Ty, Field1Off, Field2Ty, Field2Off))
@@ -369,7 +371,7 @@ ABIArgInfo LoongArchABIInfo::classifyArgumentType(QualType Ty, bool IsFixed,
if (!isAggregateTypeForABI(Ty) && !Ty->isVectorType()) {
// Treat an enum type as its underlying type.
if (const EnumType *EnumTy = Ty->getAs<EnumType>())
- Ty = EnumTy->getDecl()->getIntegerType();
+ Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
// All integral types are promoted to GRLen width.
if (Size < GRLen && Ty->isIntegralOrEnumerationType())
diff --git a/clang/lib/CodeGen/Targets/Mips.cpp b/clang/lib/CodeGen/Targets/Mips.cpp
index c025f7312959c..e12a34ce07bbe 100644
--- a/clang/lib/CodeGen/Targets/Mips.cpp
+++ b/clang/lib/CodeGen/Targets/Mips.cpp
@@ -161,7 +161,7 @@ llvm::Type* MipsABIInfo::HandleAggregates(QualType Ty, uint64_t TySize) const {
return llvm::StructType::get(getVMContext(), ArgList);
}
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
assert(!(TySize % 8) && "Size of structure must be multiple of 8.");
@@ -242,7 +242,7 @@ MipsABIInfo::classifyArgumentType(QualType Ty, uint64_t &Offset) const {
// Treat an enum type as its underlying type.
if (const EnumType *EnumTy = Ty->getAs<EnumType>())
- Ty = EnumTy->getDecl()->getIntegerType();
+ Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
// Make sure we pass indirectly things that are too large.
if (const auto *EIT = Ty->getAs<BitIntType>())
@@ -265,7 +265,7 @@ MipsABIInfo::returnAggregateInRegs(QualType RetTy, uint64_t Size) const {
SmallVector<llvm::Type*, 8> RTList;
if (RT && RT->isStructureOrClassType()) {
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
unsigned FieldCnt = Layout.getFieldCount();
@@ -333,7 +333,7 @@ ABIArgInfo MipsABIInfo::classifyReturnType(QualType RetTy) const {
// Treat an enum type as its underlying type.
if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
- RetTy = EnumTy->getDecl()->getIntegerType();
+ RetTy = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
// Make sure we pass indirectly things that are too large.
if (const auto *EIT = RetTy->getAs<BitIntType>())
diff --git a/clang/lib/CodeGen/Targets/NVPTX.cpp b/clang/lib/CodeGen/Targets/NVPTX.cpp
index 82bdfe2666b52..e874617796f86 100644
--- a/clang/lib/CodeGen/Targets/NVPTX.cpp
+++ b/clang/lib/CodeGen/Targets/NVPTX.cpp
@@ -133,7 +133,7 @@ bool NVPTXABIInfo::isUnsupportedType(QualType T) const {
const auto *RT = T->getAs<RecordType>();
if (!RT)
return false;
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
// If this is a C++ record, check the bases first.
if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))
@@ -174,7 +174,7 @@ ABIArgInfo NVPTXABIInfo::classifyReturnType(QualType RetTy) const {
// Treat an enum type as its underlying type.
if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
- RetTy = EnumTy->getDecl()->getIntegerType();
+ RetTy = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
return (isPromotableIntegerTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy)
: ABIArgInfo::getDirect());
@@ -183,7 +183,7 @@ ABIArgInfo NVPTXABIInfo::classifyReturnType(QualType RetTy) const {
ABIArgInfo NVPTXABIInfo::classifyArgumentType(QualType Ty) const {
// Treat an enum type as its underlying type.
if (const EnumType *EnumTy = Ty->getAs<EnumType>())
- Ty = EnumTy->getDecl()->getIntegerType();
+ Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
// Return aggregates type as indirect by value
if (isAggregateTypeForABI(Ty)) {
diff --git a/clang/lib/CodeGen/Targets/PNaCl.cpp b/clang/lib/CodeGen/Targets/PNaCl.cpp
index 358010785850e..a2610950f24be 100644
--- a/clang/lib/CodeGen/Targets/PNaCl.cpp
+++ b/clang/lib/CodeGen/Targets/PNaCl.cpp
@@ -68,7 +68,7 @@ ABIArgInfo PNaClABIInfo::classifyArgumentType(QualType Ty) const {
return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace());
} else if (const EnumType *EnumTy = Ty->getAs<EnumType>()) {
// Treat an enum type as its underlying type.
- Ty = EnumTy->getDecl()->getIntegerType();
+ Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
} else if (Ty->isFloatingType()) {
// Floating-point types don't go inreg.
return ABIArgInfo::getDirect();
@@ -102,7 +102,7 @@ ABIArgInfo PNaClABIInfo::classifyReturnType(QualType RetTy) const {
// Treat an enum type as its underlying type.
if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
- RetTy = EnumTy->getDecl()->getIntegerType();
+ RetTy = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
return (isPromotableIntegerTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy)
: ABIArgInfo::getDirect());
diff --git a/clang/lib/CodeGen/Targets/PPC.cpp b/clang/lib/CodeGen/Targets/PPC.cpp
index 4df4c9f3c3475..38e76399299ec 100644
--- a/clang/lib/CodeGen/Targets/PPC.cpp
+++ b/clang/lib/CodeGen/Targets/PPC.cpp
@@ -154,7 +154,7 @@ class AIXTargetCodeGenInfo : public TargetCodeGenInfo {
bool AIXABIInfo::isPromotableTypeForABI(QualType Ty) const {
// Treat an enum type as its underlying type.
if (const EnumType *EnumTy = Ty->getAs<EnumType>())
- Ty = EnumTy->getDecl()->getIntegerType();
+ Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
// Promotable integer types are required to be promoted by the ABI.
if (getContext().isPromotableIntegerType(Ty))
@@ -295,7 +295,9 @@ void AIXTargetCodeGenInfo::setTargetAttributes(
unsigned Alignment = Context.toBits(Context.getDeclAlign(D)) / 8;
const auto *Ty = VarD->getType().getTypePtr();
const RecordDecl *RDecl =
- Ty->isRecordType() ? Ty->getAs<RecordType>()->getDecl() : nullptr;
+ Ty->isRecordType()
+ ? Ty->getAs<RecordType>()->getOriginalDecl()->getDefinitionOrSelf()
+ : nullptr;
bool EmitDiagnostic = UserSpecifiedTOC && GV->hasExternalLinkage();
auto reportUnsupportedWarning = [&](bool ShouldEmitWarning, StringRef Msg) {
@@ -707,7 +709,7 @@ bool
PPC64_SVR4_ABIInfo::isPromotableTypeForABI(QualType Ty) const {
// Treat an enum type as its underlying type.
if (const EnumType *EnumTy = Ty->getAs<EnumType>())
- Ty = EnumTy->getDecl()->getIntegerType();
+ Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
// Promotable integer types are required to be promoted by the ABI.
if (isPromotableIntegerTypeForABI(Ty))
diff --git a/clang/lib/CodeGen/Targets/RISCV.cpp b/clang/lib/CodeGen/Targets/RISCV.cpp
index cc3d487da83b5..6600efad3657b 100644
--- a/clang/lib/CodeGen/Targets/RISCV.cpp
+++ b/clang/lib/CodeGen/Targets/RISCV.cpp
@@ -228,7 +228,7 @@ bool RISCVABIInfo::detectFPCCEligibleStructHelper(QualType Ty, CharUnits CurOff,
// Non-zero-length arrays of empty records make the struct ineligible for
// the FP calling convention in C++.
if (const auto *RTy = EltTy->getAs<RecordType>()) {
- if (ArraySize != 0 && isa<CXXRecordDecl>(RTy->getDecl()) &&
+ if (ArraySize != 0 && isa<CXXRecordDecl>(RTy->getOriginalDecl()) &&
isEmptyRecord(getContext(), EltTy, true, true))
return false;
}
@@ -250,7 +250,7 @@ bool RISCVABIInfo::detectFPCCEligibleStructHelper(QualType Ty, CharUnits CurOff,
return false;
if (isEmptyRecord(getContext(), Ty, true, true))
return true;
- const RecordDecl *RD = RTy->getDecl();
+ const RecordDecl *RD = RTy->getOriginalDecl()->getDefinitionOrSelf();
// Unions aren't eligible unless they're empty (which is caught above).
if (RD->isUnion())
return false;
@@ -259,7 +259,9 @@ bool RISCVABIInfo::detectFPCCEligibleStructHelper(QualType Ty, CharUnits CurOff,
if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
for (const CXXBaseSpecifier &B : CXXRD->bases()) {
const auto *BDecl =
- cast<CXXRecordDecl>(B.getType()->castAs<RecordType>()->getDecl());
+ cast<CXXRecordDecl>(
+ B.getType()->castAs<RecordType>()->getOriginalDecl())
+ ->getDefinitionOrSelf();
CharUnits BaseOff = Layout.getBaseClassOffset(BDecl);
bool Ret = detectFPCCEligibleStructHelper(B.getType(), CurOff + BaseOff,
Field1Ty, Field1Off, Field2Ty,
@@ -697,7 +699,7 @@ ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed,
if (!isAggregateTypeForABI(Ty) && !Ty->isVectorType()) {
// Treat an enum type as its underlying type.
if (const EnumType *EnumTy = Ty->getAs<EnumType>())
- Ty = EnumTy->getDecl()->getIntegerType();
+ Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
// All integral types are promoted to XLen width
if (Size < XLen && Ty->isIntegralOrEnumerationType()) {
diff --git a/clang/lib/CodeGen/Targets/SPIR.cpp b/clang/lib/CodeGen/Targets/SPIR.cpp
index a66de79ed7cd1..8daabe48ad3be 100644
--- a/clang/lib/CodeGen/Targets/SPIR.cpp
+++ b/clang/lib/CodeGen/Targets/SPIR.cpp
@@ -119,7 +119,7 @@ ABIArgInfo SPIRVABIInfo::classifyReturnType(QualType RetTy) const {
return DefaultABIInfo::classifyReturnType(RetTy);
if (const RecordType *RT = RetTy->getAs<RecordType>()) {
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
if (RD->hasFlexibleArrayMember())
return DefaultABIInfo::classifyReturnType(RetTy);
}
@@ -187,7 +187,7 @@ ABIArgInfo SPIRVABIInfo::classifyArgumentType(QualType Ty) const {
RAA == CGCXXABI::RAA_DirectInMemory);
if (const RecordType *RT = Ty->getAs<RecordType>()) {
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
if (RD->hasFlexibleArrayMember())
return DefaultABIInfo::classifyArgumentType(Ty);
}
@@ -432,7 +432,7 @@ static llvm::Type *getInlineSpirvType(CodeGenModule &CGM,
case SpirvOperandKind::TypeId: {
QualType TypeOperand = Operand.getResultType();
if (auto *RT = TypeOperand->getAs<RecordType>()) {
- auto *RD = RT->getDecl();
+ auto *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
assert(RD->isCompleteDefinition() &&
"Type completion should have been required in Sema");
diff --git a/clang/lib/CodeGen/Targets/Sparc.cpp b/clang/lib/CodeGen/Targets/Sparc.cpp
index 9642196b78c63..1547bed7ea8b2 100644
--- a/clang/lib/CodeGen/Targets/Sparc.cpp
+++ b/clang/lib/CodeGen/Targets/Sparc.cpp
@@ -238,7 +238,7 @@ SparcV9ABIInfo::classifyType(QualType Ty, unsigned SizeLimit) const {
// Treat an enum type as its underlying type.
if (const EnumType *EnumTy = Ty->getAs<EnumType>())
- Ty = EnumTy->getDecl()->getIntegerType();
+ Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
// Integer types smaller than a register are extended.
if (Size < 64 && Ty->isIntegerType())
diff --git a/clang/lib/CodeGen/Targets/SystemZ.cpp b/clang/lib/CodeGen/Targets/SystemZ.cpp
index 6ea6c7a546436..38cc4d39126be 100644
--- a/clang/lib/CodeGen/Targets/SystemZ.cpp
+++ b/clang/lib/CodeGen/Targets/SystemZ.cpp
@@ -146,7 +146,7 @@ class SystemZTargetCodeGenInfo : public TargetCodeGenInfo {
bool SystemZABIInfo::isPromotableIntegerTypeForABI(QualType Ty) const {
// Treat an enum type as its underlying type.
if (const EnumType *EnumTy = Ty->getAs<EnumType>())
- Ty = EnumTy->getDecl()->getIntegerType();
+ Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
// Promotable integer types are required to be promoted by the ABI.
if (ABIInfo::isPromotableIntegerTypeForABI(Ty))
@@ -211,7 +211,7 @@ QualType SystemZABIInfo::GetSingleElementType(QualType Ty) const {
const RecordType *RT = Ty->getAs<RecordType>();
if (RT && RT->isStructureOrClassType()) {
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
QualType Found;
// If this is a C++ record, check the bases first.
@@ -455,7 +455,7 @@ ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const {
if (const RecordType *RT = Ty->getAs<RecordType>()) {
// Structures with flexible arrays have variable length, so really
// fail the size test above.
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
if (RD->hasFlexibleArrayMember())
return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
/*ByVal=*/false);
@@ -526,7 +526,7 @@ bool SystemZTargetCodeGenInfo::isVectorTypeBased(const Type *Ty,
return true;
if (const auto *RecordTy = Ty->getAs<RecordType>()) {
- const RecordDecl *RD = RecordTy->getDecl();
+ const RecordDecl *RD = RecordTy->getOriginalDecl()->getDefinitionOrSelf();
if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))
if (CXXRD->hasDefinition())
for (const auto &I : CXXRD->bases())
diff --git a/clang/lib/CodeGen/Targets/WebAssembly.cpp b/clang/lib/CodeGen/Targets/WebAssembly.cpp
index 9217c78a540a3..ac8dcd2a0540a 100644
--- a/clang/lib/CodeGen/Targets/WebAssembly.cpp
+++ b/clang/lib/CodeGen/Targets/WebAssembly.cpp
@@ -118,7 +118,8 @@ ABIArgInfo WebAssemblyABIInfo::classifyArgumentType(QualType Ty) const {
const RecordType *RT = Ty->getAs<RecordType>();
assert(RT);
bool HasBitField = false;
- for (auto *Field : RT->getDecl()->fields()) {
+ for (auto *Field :
+ RT->getOriginalDecl()->getDefinitionOrSelf()->fields()) {
if (Field->isBitField()) {
HasBitField = true;
break;
diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp
index 0f59caac2323e..51d144e2f223a 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -359,7 +359,8 @@ bool X86_32ABIInfo::shouldReturnTypeInRegister(QualType Ty,
// Structure types are passed in register if all fields would be
// passed in a register.
- for (const auto *FD : RT->getDecl()->fields()) {
+ for (const auto *FD :
+ RT->getOriginalDecl()->getDefinitionOrSelf()->fields()) {
// Empty fields are ignored.
if (isEmptyField(Context, FD, true))
continue;
@@ -429,9 +430,9 @@ bool X86_32ABIInfo::canExpandIndirectArgument(QualType Ty) const {
const RecordType *RT = Ty->getAs<RecordType>();
if (!RT)
return false;
- const RecordDecl *RD = RT->getDecl();
uint64_t Size = 0;
- if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
+ if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
if (!IsWin32StructABI) {
// On non-Windows, we have to conservatively match our old bitcode
// prototypes in order to be ABI-compatible at the bitcode level.
@@ -509,7 +510,9 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy,
if (isAggregateTypeForABI(RetTy)) {
if (const RecordType *RT = RetTy->getAs<RecordType>()) {
// Structures with flexible arrays are always indirect.
- if (RT->getDecl()->hasFlexibleArrayMember())
+ if (RT->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->hasFlexibleArrayMember())
return getIndirectReturnResult(RetTy, State);
}
@@ -554,7 +557,7 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy,
// Treat an enum type as its underlying type.
if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
- RetTy = EnumTy->getDecl()->getIntegerType();
+ RetTy = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
if (const auto *EIT = RetTy->getAs<BitIntType>())
if (EIT->getNumBits() > 64)
@@ -796,7 +799,8 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState &State,
if (isAggregateTypeForABI(Ty)) {
// Structures with flexible arrays are always indirect.
// FIXME: This should not be byval!
- if (RT && RT->getDecl()->hasFlexibleArrayMember())
+ if (RT &&
+ RT->getOriginalDecl()->getDefinitionOrSelf()->hasFlexibleArrayMember())
return getIndirectResult(Ty, true, State);
// Ignore empty structs/unions on non-Windows.
@@ -831,7 +835,7 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState &State,
unsigned AlignInBits = 0;
if (RT) {
const ASTRecordLayout &Layout =
- getContext().getASTRecordLayout(RT->getDecl());
+ getContext().getASTRecordLayout(RT->getOriginalDecl());
AlignInBits = getContext().toBits(Layout.getRequiredAlignment());
} else if (TI.isAlignRequired()) {
AlignInBits = TI.Align;
@@ -883,7 +887,7 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState &State,
if (const EnumType *EnumTy = Ty->getAs<EnumType>())
- Ty = EnumTy->getDecl()->getIntegerType();
+ Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
bool InReg = shouldPrimitiveUseInReg(Ty, State);
@@ -1847,7 +1851,8 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, Class &Lo,
if (const EnumType *ET = Ty->getAs<EnumType>()) {
// Classify the underlying integer type.
- classify(ET->getDecl()->getIntegerType(), OffsetBase, Lo, Hi, isNamedArg);
+ classify(ET->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(),
+ OffsetBase, Lo, Hi, isNamedArg);
return;
}
@@ -2053,7 +2058,7 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, Class &Lo,
if (getRecordArgABI(RT, getCXXABI()))
return;
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
// Assume variable sized types are passed in memory.
if (RD->hasFlexibleArrayMember())
@@ -2070,7 +2075,9 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, Class &Lo,
assert(!I.isVirtual() && !I.getType()->isDependentType() &&
"Unexpected base class!");
const auto *Base =
- cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl());
+ cast<CXXRecordDecl>(
+ I.getType()->castAs<RecordType>()->getOriginalDecl())
+ ->getDefinitionOrSelf();
// Classify this field.
//
@@ -2184,7 +2191,7 @@ ABIArgInfo X86_64ABIInfo::getIndirectReturnResult(QualType Ty) const {
if (!isAggregateTypeForABI(Ty)) {
// Treat an enum type as its underlying type.
if (const EnumType *EnumTy = Ty->getAs<EnumType>())
- Ty = EnumTy->getDecl()->getIntegerType();
+ Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
if (Ty->isBitIntType())
return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace());
@@ -2226,7 +2233,7 @@ ABIArgInfo X86_64ABIInfo::getIndirectResult(QualType Ty,
!Ty->isBitIntType()) {
// Treat an enum type as its underlying type.
if (const EnumType *EnumTy = Ty->getAs<EnumType>())
- Ty = EnumTy->getDecl()->getIntegerType();
+ Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
return (isPromotableIntegerTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty)
: ABIArgInfo::getDirect());
@@ -2347,7 +2354,7 @@ static bool BitsContainNoUserData(QualType Ty, unsigned StartBit,
}
if (const RecordType *RT = Ty->getAs<RecordType>()) {
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
// If this is a C++ record, check the bases first.
@@ -2356,7 +2363,9 @@ static bool BitsContainNoUserData(QualType Ty, unsigned StartBit,
assert(!I.isVirtual() && !I.getType()->isDependentType() &&
"Unexpected base class!");
const auto *Base =
- cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl());
+ cast<CXXRecordDecl>(
+ I.getType()->castAs<RecordType>()->getOriginalDecl())
+ ->getDefinitionOrSelf();
// If the base is after the span we care about, ignore it.
unsigned BaseOffset = Context.toBits(Layout.getBaseClassOffset(Base));
@@ -2633,7 +2642,8 @@ classifyReturnType(QualType RetTy) const {
if (Hi == NoClass && isa<llvm::IntegerType>(ResType)) {
// Treat an enum type as its underlying type.
if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
- RetTy = EnumTy->getDecl()->getIntegerType();
+ RetTy =
+ EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
if (RetTy->isIntegralOrEnumerationType() &&
isPromotableIntegerTypeForABI(RetTy))
@@ -2777,7 +2787,7 @@ X86_64ABIInfo::classifyArgumentType(QualType Ty, unsigned freeIntRegs,
if (Hi == NoClass && isa<llvm::IntegerType>(ResType)) {
// Treat an enum type as its underlying type.
if (const EnumType *EnumTy = Ty->getAs<EnumType>())
- Ty = EnumTy->getDecl()->getIntegerType();
+ Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
if (Ty->isIntegralOrEnumerationType() &&
isPromotableIntegerTypeForABI(Ty))
@@ -2851,14 +2861,15 @@ ABIArgInfo
X86_64ABIInfo::classifyRegCallStructTypeImpl(QualType Ty, unsigned &NeededInt,
unsigned &NeededSSE,
unsigned &MaxVectorWidth) const {
- auto RT = Ty->getAs<RecordType>();
- assert(RT && "classifyRegCallStructType only valid with struct types");
+ auto *RD = cast<RecordType>(Ty.getCanonicalType())
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf();
- if (RT->getDecl()->hasFlexibleArrayMember())
+ if (RD->hasFlexibleArrayMember())
return getIndirectReturnResult(Ty);
// Sum up bases
- if (auto CXXRD = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
+ if (auto CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
if (CXXRD->isDynamicClass()) {
NeededInt = NeededSSE = 0;
return getIndirectReturnResult(Ty);
@@ -2874,7 +2885,7 @@ X86_64ABIInfo::classifyRegCallStructTypeImpl(QualType Ty, unsigned &NeededInt,
}
// Sum up members
- for (const auto *FD : RT->getDecl()->fields()) {
+ for (const auto *FD : RD->fields()) {
QualType MTy = FD->getType();
if (MTy->isRecordType() && !MTy->isUnionType()) {
if (classifyRegCallStructTypeImpl(MTy, NeededInt, NeededSSE,
@@ -3298,7 +3309,7 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty, unsigned &FreeSSERegs,
return ABIArgInfo::getIgnore();
if (const EnumType *EnumTy = Ty->getAs<EnumType>())
- Ty = EnumTy->getDecl()->getIntegerType();
+ Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
TypeInfo Info = getContext().getTypeInfo(Ty);
uint64_t Width = Info.Width;
@@ -3312,7 +3323,7 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty, unsigned &FreeSSERegs,
RAA == CGCXXABI::RAA_DirectInMemory);
}
- if (RT->getDecl()->hasFlexibleArrayMember())
+ if (RT->getOriginalDecl()->getDefinitionOrSelf()->hasFlexibleArrayMember())
return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
/*ByVal=*/false);
}
diff --git a/clang/lib/CodeGen/Targets/XCore.cpp b/clang/lib/CodeGen/Targets/XCore.cpp
index b7824bde5f55a..aa6947b1d956b 100644
--- a/clang/lib/CodeGen/Targets/XCore.cpp
+++ b/clang/lib/CodeGen/Targets/XCore.cpp
@@ -379,7 +379,7 @@ static bool appendRecordType(SmallStringEnc &Enc, const RecordType *RT,
// We collect all encoded fields and order as necessary.
bool IsRecursive = false;
- const RecordDecl *RD = RT->getDecl()->getDefinition();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinition();
if (RD && !RD->field_empty()) {
// An incomplete TypeString stub is placed in the cache for this RecordType
// so that recursive calls to this RecordType will use it whilst building a
@@ -428,7 +428,7 @@ static bool appendEnumType(SmallStringEnc &Enc, const EnumType *ET,
Enc += "){";
// We collect all encoded enumerations and order them alphanumerically.
- if (const EnumDecl *ED = ET->getDecl()->getDefinition()) {
+ if (const EnumDecl *ED = ET->getOriginalDecl()->getDefinition()) {
SmallVector<FieldEncoding, 16> FE;
for (auto I = ED->enumerator_begin(), E = ED->enumerator_end(); I != E;
++I) {
diff --git a/clang/lib/ExtractAPI/DeclarationFragments.cpp b/clang/lib/ExtractAPI/DeclarationFragments.cpp
index 791afc1a97575..d3d549c0127bf 100644
--- a/clang/lib/ExtractAPI/DeclarationFragments.cpp
+++ b/clang/lib/ExtractAPI/DeclarationFragments.cpp
@@ -205,54 +205,39 @@ DeclarationFragments::getStructureTypeFragment(const RecordDecl *Record) {
// Build declaration fragments for NNS recursively so that we have the USR for
// every part in a qualified name, and also leaves the actual underlying type
// cleaner for its own fragment.
-DeclarationFragments
-DeclarationFragmentsBuilder::getFragmentsForNNS(const NestedNameSpecifier *NNS,
- ASTContext &Context,
- DeclarationFragments &After) {
+DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForNNS(
+ NestedNameSpecifier NNS, ASTContext &Context, DeclarationFragments &After) {
DeclarationFragments Fragments;
- if (NNS->getPrefix())
- Fragments.append(getFragmentsForNNS(NNS->getPrefix(), Context, After));
-
- switch (NNS->getKind()) {
- case NestedNameSpecifier::Identifier:
- Fragments.append(NNS->getAsIdentifier()->getName(),
- DeclarationFragments::FragmentKind::Identifier);
- break;
+ switch (NNS.getKind()) {
+ case NestedNameSpecifier::Kind::Null:
+ return Fragments;
- case NestedNameSpecifier::Namespace: {
- const NamespaceDecl *NS = NNS->getAsNamespace();
- if (NS->isAnonymousNamespace())
+ case NestedNameSpecifier::Kind::Namespace: {
+ auto [Namespace, Prefix] = NNS.getAsNamespaceAndPrefix();
+ Fragments.append(getFragmentsForNNS(Prefix, Context, After));
+ if (const auto *NS = dyn_cast<NamespaceDecl>(Namespace);
+ NS && NS->isAnonymousNamespace())
return Fragments;
SmallString<128> USR;
- index::generateUSRForDecl(NS, USR);
- Fragments.append(NS->getName(),
- DeclarationFragments::FragmentKind::Identifier, USR, NS);
- break;
- }
-
- case NestedNameSpecifier::NamespaceAlias: {
- const NamespaceAliasDecl *Alias = NNS->getAsNamespaceAlias();
- SmallString<128> USR;
- index::generateUSRForDecl(Alias, USR);
- Fragments.append(Alias->getName(),
+ index::generateUSRForDecl(Namespace, USR);
+ Fragments.append(Namespace->getName(),
DeclarationFragments::FragmentKind::Identifier, USR,
- Alias);
+ Namespace);
break;
}
- case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Kind::Global:
// The global specifier `::` at the beginning. No stored value.
break;
- case NestedNameSpecifier::Super:
+ case NestedNameSpecifier::Kind::Super:
// Microsoft's `__super` specifier.
Fragments.append("__super", DeclarationFragments::FragmentKind::Keyword);
break;
- case NestedNameSpecifier::TypeSpec: {
- const Type *T = NNS->getAsType();
+ case NestedNameSpecifier::Kind::Type: {
// FIXME: Handle C++ template specialization type
- Fragments.append(getFragmentsForType(T, Context, After));
+ Fragments.append(getFragmentsForType(NNS.getAsType(), Context, After));
break;
}
}
@@ -282,26 +267,6 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(
return Fragments;
}
- // An ElaboratedType is a sugar for types that are referred to using an
- // elaborated keyword, e.g., `struct S`, `enum E`, or (in C++) via a
- // qualified name, e.g., `N::M::type`, or both.
- if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(T)) {
- ElaboratedTypeKeyword Keyword = ET->getKeyword();
- if (Keyword != ElaboratedTypeKeyword::None) {
- Fragments
- .append(ElaboratedType::getKeywordName(Keyword),
- DeclarationFragments::FragmentKind::Keyword)
- .appendSpace();
- }
-
- if (const NestedNameSpecifier *NNS = ET->getQualifier())
- Fragments.append(getFragmentsForNNS(NNS, Context, After));
-
- // After handling the elaborated keyword or qualified name, build
- // declaration fragments for the desugared underlying type.
- return Fragments.append(getFragmentsForType(ET->desugar(), Context, After));
- }
-
// If the type is a typedefed type, get the underlying TypedefNameDecl for a
// direct reference to the typedef instead of the wrapped type.
@@ -312,7 +277,18 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(
TypedefUnderlyingTypeResolver TypedefResolver(Context);
std::string USR = TypedefResolver.getUSRForType(QualType(T, 0));
- if (T->isObjCIdType()) {
+ if (ElaboratedTypeKeyword Keyword = TypedefTy->getKeyword();
+ Keyword != ElaboratedTypeKeyword::None) {
+ Fragments
+ .append(KeywordHelpers::getKeywordName(Keyword),
+ DeclarationFragments::FragmentKind::Keyword)
+ .appendSpace();
+ }
+
+ Fragments.append(
+ getFragmentsForNNS(TypedefTy->getQualifier(), Context, After));
+
+ if (TypedefTy->isObjCIdType()) {
return Fragments.append(Decl->getName(),
DeclarationFragments::FragmentKind::Keyword);
}
@@ -405,14 +381,26 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(
if (const TemplateSpecializationType *TemplSpecTy =
dyn_cast<TemplateSpecializationType>(T)) {
- const auto TemplName = TemplSpecTy->getTemplateName();
+ if (ElaboratedTypeKeyword Keyword = TemplSpecTy->getKeyword();
+ Keyword != ElaboratedTypeKeyword::None)
+ Fragments
+ .append(KeywordHelpers::getKeywordName(Keyword),
+ DeclarationFragments::FragmentKind::Keyword)
+ .appendSpace();
+
+ auto TemplName = TemplSpecTy->getTemplateName();
std::string Str;
raw_string_ostream Stream(Str);
TemplName.print(Stream, Context.getPrintingPolicy(),
TemplateName::Qualified::AsWritten);
SmallString<64> USR("");
+ if (const auto *QTN = TemplName.getAsQualifiedTemplateName()) {
+ Fragments.append(getFragmentsForNNS(QTN->getQualifier(), Context, After));
+ TemplName = QTN->getUnderlyingTemplate();
+ }
if (const auto *TemplDecl = TemplName.getAsTemplateDecl())
index::generateUSRForDecl(TemplDecl, USR);
+ // FIXME: Handle other kinds of TemplateNames.
return Fragments
.append(Str, DeclarationFragments::FragmentKind::TypeIdentifier, USR)
@@ -422,14 +410,19 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(
.append(">", DeclarationFragments::FragmentKind::Text);
}
- // Everything we care about has been handled now, reduce to the canonical
- // unqualified base type.
- QualType Base = T->getCanonicalTypeUnqualified();
-
// If the base type is a TagType (struct/interface/union/class/enum), let's
// get the underlying Decl for better names and USRs.
- if (const TagType *TagTy = dyn_cast<TagType>(Base)) {
- const TagDecl *Decl = TagTy->getDecl();
+ if (const TagType *TagTy = dyn_cast<TagType>(T)) {
+ if (ElaboratedTypeKeyword Keyword = TagTy->getKeyword();
+ Keyword != ElaboratedTypeKeyword::None)
+ Fragments
+ .append(KeywordHelpers::getKeywordName(Keyword),
+ DeclarationFragments::FragmentKind::Keyword)
+ .appendSpace();
+
+ Fragments.append(getFragmentsForNNS(TagTy->getQualifier(), Context, After));
+
+ const TagDecl *Decl = TagTy->getOriginalDecl();
// Anonymous decl, skip this fragment.
if (Decl->getName().empty())
return Fragments.append("{ ... }",
@@ -441,6 +434,10 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(
TagUSR, Decl);
}
+ // Everything we care about has been handled now, reduce to the canonical
+ // unqualified base type.
+ QualType Base = T->getCanonicalTypeUnqualified();
+
// If the base type is an ObjCInterfaceType, use the underlying
// ObjCInterfaceDecl for the true USR.
if (const auto *ObjCIT = dyn_cast<ObjCInterfaceType>(Base)) {
diff --git a/clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.cpp b/clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.cpp
index 41e4e0cf1795f..5adbbc6d1c34c 100644
--- a/clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.cpp
+++ b/clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.cpp
@@ -26,7 +26,7 @@ TypedefUnderlyingTypeResolver::getUnderlyingTypeDecl(QualType Type) const {
if (TypedefTy)
TypeDecl = TypedefTy->getDecl();
if (const TagType *TagTy = Type->getAs<TagType>()) {
- TypeDecl = TagTy->getDecl();
+ TypeDecl = TagTy->getOriginalDecl();
} else if (const ObjCInterfaceType *ObjCITy =
Type->getAs<ObjCInterfaceType>()) {
TypeDecl = ObjCITy->getDecl();
diff --git a/clang/lib/Frontend/ASTConsumers.cpp b/clang/lib/Frontend/ASTConsumers.cpp
index ab8a35a189250..67c8761511e0c 100644
--- a/clang/lib/Frontend/ASTConsumers.cpp
+++ b/clang/lib/Frontend/ASTConsumers.cpp
@@ -97,6 +97,7 @@ namespace {
Out << "Not a DeclContext\n";
} else if (OutputKind == Print) {
PrintingPolicy Policy(D->getASTContext().getLangOpts());
+ Policy.IncludeTagDefinition = true;
D->print(Out, Policy, /*Indentation=*/0, /*PrintInstantiation=*/true);
} else if (OutputKind != None) {
D->dump(Out, OutputKind == DumpFull, OutputFormat);
@@ -112,8 +113,10 @@ namespace {
// FIXME: Support combining -ast-dump-decl-types with -ast-dump-lookups.
if (auto *VD = dyn_cast<ValueDecl>(InnerD))
VD->getType().dump(Out, VD->getASTContext());
- if (auto *TD = dyn_cast<TypeDecl>(InnerD))
- TD->getTypeForDecl()->dump(Out, TD->getASTContext());
+ if (auto *TD = dyn_cast<TypeDecl>(InnerD)) {
+ const ASTContext &Ctx = TD->getASTContext();
+ Ctx.getTypeDeclType(TD)->dump(Out, Ctx);
+ }
}
}
diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp
index 4ebec8e074330..2f2cc12b3fe30 100644
--- a/clang/lib/Frontend/ASTUnit.cpp
+++ b/clang/lib/Frontend/ASTUnit.cpp
@@ -395,7 +395,7 @@ void ASTUnit::CacheCodeCompletionResults() {
// Keep track of the type of this completion in an ASTContext-agnostic
// way.
- QualType UsageType = getDeclUsageType(*Ctx, R.Declaration);
+ QualType UsageType = getDeclUsageType(*Ctx, R.Qualifier, R.Declaration);
if (UsageType.isNull()) {
CachedResult.TypeClass = STC_Void;
CachedResult.Type = 0;
diff --git a/clang/lib/Index/IndexTypeSourceInfo.cpp b/clang/lib/Index/IndexTypeSourceInfo.cpp
index 98b5513128fbe..8868aea53f10b 100644
--- a/clang/lib/Index/IndexTypeSourceInfo.cpp
+++ b/clang/lib/Index/IndexTypeSourceInfo.cpp
@@ -59,7 +59,7 @@ class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> {
bool VisitTypedefTypeLoc(TypedefTypeLoc TL) {
SourceLocation Loc = TL.getNameLoc();
- TypedefNameDecl *ND = TL.getTypedefNameDecl();
+ TypedefNameDecl *ND = TL.getDecl();
if (ND->isTransparentTag()) {
TagDecl *Underlying = ND->getUnderlyingType()->getAsTagDecl();
return IndexCtx.handleReference(Underlying, Loc, Parent,
@@ -117,7 +117,7 @@ class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> {
}
bool VisitTagTypeLoc(TagTypeLoc TL) {
- TagDecl *D = TL.getDecl();
+ TagDecl *D = TL.getOriginalDecl();
if (!IndexCtx.shouldIndexFunctionLocalSymbols() &&
D->getParentFunctionOrMethod())
return true;
@@ -172,7 +172,8 @@ class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> {
return true;
}
- bool TraverseTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
+ bool TraverseTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL,
+ bool TraverseQualifier) {
if (!WalkUpFromTemplateSpecializationTypeLoc(TL))
return false;
if (!TraverseTemplateName(TL.getTypePtr()->getTemplateName()))
@@ -202,11 +203,6 @@ class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> {
return true;
}
- bool VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) {
- return IndexCtx.handleReference(TL.getDecl(), TL.getNameLoc(), Parent,
- ParentDC, SymbolRoleSet(), Relations);
- }
-
bool VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
std::vector<const NamedDecl *> Symbols =
IndexCtx.getResolver()->resolveDependentNameType(TL.getTypePtr());
@@ -248,36 +244,28 @@ void IndexingContext::indexTypeLoc(TypeLoc TL,
TypeIndexer(*this, Parent, DC, isBase, isIBType).TraverseTypeLoc(TL);
}
-void IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
- const NamedDecl *Parent,
- const DeclContext *DC) {
- if (!NNS)
- return;
-
- if (NestedNameSpecifierLoc Prefix = NNS.getPrefix())
- indexNestedNameSpecifierLoc(Prefix, Parent, DC);
-
+void IndexingContext::indexNestedNameSpecifierLoc(
+ NestedNameSpecifierLoc QualifierLoc, const NamedDecl *Parent,
+ const DeclContext *DC) {
if (!DC)
DC = Parent->getLexicalDeclContext();
- SourceLocation Loc = NNS.getLocalBeginLoc();
-
- switch (NNS.getNestedNameSpecifier()->getKind()) {
- case NestedNameSpecifier::Identifier:
- case NestedNameSpecifier::Global:
- case NestedNameSpecifier::Super:
+ switch (NestedNameSpecifier Qualifier = QualifierLoc.getNestedNameSpecifier();
+ Qualifier.getKind()) {
+ case NestedNameSpecifier::Kind::Null:
+ case NestedNameSpecifier::Kind::Global:
+ case NestedNameSpecifier::Kind::Super:
break;
- case NestedNameSpecifier::Namespace:
- handleReference(NNS.getNestedNameSpecifier()->getAsNamespace(),
- Loc, Parent, DC, SymbolRoleSet());
- break;
- case NestedNameSpecifier::NamespaceAlias:
- handleReference(NNS.getNestedNameSpecifier()->getAsNamespaceAlias(),
- Loc, Parent, DC, SymbolRoleSet());
+ case NestedNameSpecifier::Kind::Namespace: {
+ auto [Namespace, Prefix] = QualifierLoc.castAsNamespaceAndPrefix();
+ indexNestedNameSpecifierLoc(Prefix, Parent, DC);
+ handleReference(Namespace, QualifierLoc.getLocalBeginLoc(), Parent, DC,
+ SymbolRoleSet());
break;
+ }
- case NestedNameSpecifier::TypeSpec:
- indexTypeLoc(NNS.getTypeLoc(), Parent, DC);
+ case NestedNameSpecifier::Kind::Type:
+ indexTypeLoc(QualifierLoc.castAsTypeLoc(), Parent, DC);
break;
}
}
diff --git a/clang/lib/Index/USRGeneration.cpp b/clang/lib/Index/USRGeneration.cpp
index 6a884f7be00e1..9e69ca567e80c 100644
--- a/clang/lib/Index/USRGeneration.cpp
+++ b/clang/lib/Index/USRGeneration.cpp
@@ -653,14 +653,14 @@ bool USRGenerator::GenLoc(const Decl *D, bool IncludeOffset) {
}
static void printQualifier(llvm::raw_ostream &Out, const LangOptions &LangOpts,
- NestedNameSpecifier *NNS) {
+ NestedNameSpecifier NNS) {
// FIXME: Encode the qualifier, don't just print it.
PrintingPolicy PO(LangOpts);
PO.SuppressTagKeyword = true;
PO.SuppressUnwrittenScope = true;
PO.ConstantArraySizeAsWritten = false;
PO.AnonymousTagLocations = false;
- NNS->print(Out, PO);
+ NNS.print(Out, PO);
}
void USRGenerator::VisitType(QualType T) {
@@ -910,9 +910,13 @@ void USRGenerator::VisitType(QualType T) {
continue;
}
if (const TagType *TT = T->getAs<TagType>()) {
- Out << '$';
- VisitTagDecl(TT->getDecl());
- return;
+ if (const auto *ICNT = dyn_cast<InjectedClassNameType>(TT)) {
+ T = ICNT->getCanonicalInjectedTST();
+ } else {
+ Out << '$';
+ VisitTagDecl(TT->getOriginalDecl());
+ return;
+ }
}
if (const ObjCInterfaceType *OIT = T->getAs<ObjCInterfaceType>()) {
Out << '$';
@@ -945,10 +949,6 @@ void USRGenerator::VisitType(QualType T) {
Out << ':' << DNT->getIdentifier()->getName();
return;
}
- if (const InjectedClassNameType *InjT = T->getAs<InjectedClassNameType>()) {
- T = InjT->getInjectedSpecializationType();
- continue;
- }
if (const auto *VT = T->getAs<VectorType>()) {
Out << (T->isExtVectorType() ? ']' : '[');
Out << VT->getNumElements();
diff --git a/clang/lib/InstallAPI/Visitor.cpp b/clang/lib/InstallAPI/Visitor.cpp
index 487be2c300887..f12e04069817b 100644
--- a/clang/lib/InstallAPI/Visitor.cpp
+++ b/clang/lib/InstallAPI/Visitor.cpp
@@ -424,7 +424,7 @@ std::string
InstallAPIVisitor::getMangledCXXRTTIName(const CXXRecordDecl *D) const {
SmallString<256> Name;
raw_svector_ostream NameStream(Name);
- MC->mangleCXXRTTIName(QualType(D->getTypeForDecl(), 0), NameStream);
+ MC->mangleCXXRTTIName(MC->getASTContext().getCanonicalTagType(D), NameStream);
return getBackendMangledName(Name);
}
@@ -432,7 +432,7 @@ InstallAPIVisitor::getMangledCXXRTTIName(const CXXRecordDecl *D) const {
std::string InstallAPIVisitor::getMangledCXXRTTI(const CXXRecordDecl *D) const {
SmallString<256> Name;
raw_svector_ostream NameStream(Name);
- MC->mangleCXXRTTI(QualType(D->getTypeForDecl(), 0), NameStream);
+ MC->mangleCXXRTTI(MC->getASTContext().getCanonicalTagType(D), NameStream);
return getBackendMangledName(Name);
}
@@ -543,8 +543,8 @@ void InstallAPIVisitor::emitVTableSymbols(const CXXRecordDecl *D,
}
for (const auto &It : D->bases()) {
- const CXXRecordDecl *Base =
- cast<CXXRecordDecl>(It.getType()->castAs<RecordType>()->getDecl());
+ const CXXRecordDecl *Base = cast<CXXRecordDecl>(
+ It.getType()->castAs<RecordType>()->getOriginalDecl());
const auto BaseAccess = getAccessForDecl(Base);
if (!BaseAccess)
continue;
diff --git a/clang/lib/Interpreter/InterpreterValuePrinter.cpp b/clang/lib/Interpreter/InterpreterValuePrinter.cpp
index 3e7e32b2e8557..00f9a7a631e36 100644
--- a/clang/lib/Interpreter/InterpreterValuePrinter.cpp
+++ b/clang/lib/Interpreter/InterpreterValuePrinter.cpp
@@ -324,7 +324,7 @@ extern "C" void REPL_EXTERNAL_VISIBILITY __clang_Interpreter_SetValueNoAlloc(
VRef.setPtr(va_arg(args, void *));
} else {
if (const auto *ET = QT->getAs<EnumType>())
- QT = ET->getDecl()->getIntegerType();
+ QT = ET->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
switch (QT->castAs<BuiltinType>()->getKind()) {
default:
llvm_unreachable("unknown type kind!");
diff --git a/clang/lib/Interpreter/Value.cpp b/clang/lib/Interpreter/Value.cpp
index afdf406b37253..526cca80a983a 100644
--- a/clang/lib/Interpreter/Value.cpp
+++ b/clang/lib/Interpreter/Value.cpp
@@ -99,7 +99,7 @@ static Value::Kind ConvertQualTypeToKind(const ASTContext &Ctx, QualType QT) {
return Value::K_Void;
if (const auto *ET = QT->getAs<EnumType>())
- QT = ET->getDecl()->getIntegerType();
+ QT = ET->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
const auto *BT = QT->getAs<BuiltinType>();
if (!BT || BT->isNullPtrType())
@@ -145,9 +145,9 @@ Value::Value(Interpreter *In, void *Ty) : Interp(In), OpaqueType(Ty) {
}
if (const auto *RT = DtorTy->getAs<RecordType>()) {
if (CXXRecordDecl *CXXRD =
- llvm::dyn_cast<CXXRecordDecl>(RT->getDecl())) {
+ llvm::dyn_cast<CXXRecordDecl>(RT->getOriginalDecl())) {
if (llvm::Expected<llvm::orc::ExecutorAddr> Addr =
- Interp.CompileDtorCall(CXXRD))
+ Interp.CompileDtorCall(CXXRD->getDefinitionOrSelf()))
DtorF = reinterpret_cast<void *>(Addr->getValue());
else
llvm::logAllUnhandledErrors(Addr.takeError(), llvm::errs());
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index eae8281964692..779958230ada2 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -591,8 +591,7 @@ bool Parser::ParseUsingDeclarator(DeclaratorContext Context,
NextToken().isRegularKeywordAttribute() ||
NextToken().is(tok::kw___attribute)) &&
D.SS.isNotEmpty() && LastII == Tok.getIdentifierInfo() &&
- !D.SS.getScopeRep()->getAsNamespace() &&
- !D.SS.getScopeRep()->getAsNamespaceAlias()) {
+ D.SS.getScopeRep().getKind() != NestedNameSpecifier::Kind::Namespace) {
SourceLocation IdLoc = ConsumeToken();
ParsedType Type =
Actions.getInheritingConstructorName(D.SS, IdLoc, *LastII);
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index 8dce2268082d9..8605ba2cdb49b 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -195,9 +195,10 @@ bool Parser::ParseOptionalCXXScopeSpecifier(
if (DS.getTypeSpecType() == DeclSpec::TST_error)
return false;
- QualType Type = Actions.ActOnPackIndexingType(
- DS.getRepAsType().get(), DS.getPackIndexingExpr(), DS.getBeginLoc(),
- DS.getEllipsisLoc());
+ QualType Pattern = Sema::GetTypeFromParser(DS.getRepAsType());
+ QualType Type =
+ Actions.ActOnPackIndexingType(Pattern, DS.getPackIndexingExpr(),
+ DS.getBeginLoc(), DS.getEllipsisLoc());
if (Type.isNull())
return false;
@@ -2355,8 +2356,10 @@ bool Parser::ParseUnqualifiedIdTemplateId(
// Constructor and destructor names.
TypeResult Type = Actions.ActOnTemplateIdType(
- getCurScope(), SS, TemplateKWLoc, Template, Name, NameLoc, LAngleLoc,
- TemplateArgsPtr, RAngleLoc, /*IsCtorOrDtorName=*/true);
+ getCurScope(), ElaboratedTypeKeyword::None,
+ /*ElaboratedKeywordLoc=*/SourceLocation(), SS, TemplateKWLoc, Template,
+ Name, NameLoc, LAngleLoc, TemplateArgsPtr, RAngleLoc,
+ /*IsCtorOrDtorName=*/true);
if (Type.isInvalid())
return true;
diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp
index 9a04bf298c0ac..004cb40445eab 100644
--- a/clang/lib/Parse/ParseTemplate.cpp
+++ b/clang/lib/Parse/ParseTemplate.cpp
@@ -1109,12 +1109,14 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
// Build the annotation token.
if (TNK == TNK_Type_template && AllowTypeAnnotation) {
- TypeResult Type = ArgsInvalid
- ? TypeError()
- : Actions.ActOnTemplateIdType(
- getCurScope(), SS, TemplateKWLoc, Template,
- TemplateName.Identifier, TemplateNameLoc,
- LAngleLoc, TemplateArgsPtr, RAngleLoc);
+ TypeResult Type =
+ ArgsInvalid
+ ? TypeError()
+ : Actions.ActOnTemplateIdType(
+ getCurScope(), ElaboratedTypeKeyword::None,
+ /*ElaboratedKeywordLoc=*/SourceLocation(), SS, TemplateKWLoc,
+ Template, TemplateName.Identifier, TemplateNameLoc, LAngleLoc,
+ TemplateArgsPtr, RAngleLoc);
Tok.setKind(tok::annot_typename);
setTypeAnnotation(Tok, Type);
@@ -1175,10 +1177,11 @@ void Parser::AnnotateTemplateIdTokenAsType(
TemplateId->isInvalid()
? TypeError()
: Actions.ActOnTemplateIdType(
- getCurScope(), SS, TemplateId->TemplateKWLoc,
- TemplateId->Template, TemplateId->Name,
- TemplateId->TemplateNameLoc, TemplateId->LAngleLoc,
- TemplateArgsPtr, TemplateId->RAngleLoc,
+ getCurScope(), ElaboratedTypeKeyword::None,
+ /*ElaboratedKeywordLoc=*/SourceLocation(), SS,
+ TemplateId->TemplateKWLoc, TemplateId->Template,
+ TemplateId->Name, TemplateId->TemplateNameLoc,
+ TemplateId->LAngleLoc, TemplateArgsPtr, TemplateId->RAngleLoc,
/*IsCtorOrDtorName=*/false, IsClassName, AllowImplicitTypename);
// Create the new "type" annotation token.
Tok.setKind(tok::annot_typename);
@@ -1243,7 +1246,8 @@ ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() {
Actions.ActOnTemplateName(getCurScope(), SS, TemplateKWLoc, Name,
/*ObjectType=*/nullptr,
/*EnteringContext=*/false, Template))
- Result = ParsedTemplateArgument(SS, Template, Name.StartLocation);
+ Result = ParsedTemplateArgument(TemplateKWLoc, SS, Template,
+ Name.StartLocation);
}
} else if (Tok.is(tok::identifier)) {
// We may have a (non-dependent) template name.
@@ -1264,7 +1268,8 @@ ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() {
if (TNK == TNK_Dependent_template_name || TNK == TNK_Type_template) {
// We have an id-expression that refers to a class template or
// (C++0x) alias template.
- Result = ParsedTemplateArgument(SS, Template, Name.StartLocation);
+ Result = ParsedTemplateArgument(/*TemplateKwLoc=*/SourceLocation(), SS,
+ Template, Name.StartLocation);
}
}
}
diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp
index 95cee824c40b7..5a4b1740f5fb5 100644
--- a/clang/lib/Parse/ParseTentative.cpp
+++ b/clang/lib/Parse/ParseTentative.cpp
@@ -1326,7 +1326,7 @@ Parser::isCXXDeclarationSpecifier(ImplicitTypenameContext AllowImplicitTypename,
Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(),
Tok.getAnnotationRange(),
SS);
- if (SS.getScopeRep() && SS.getScopeRep()->isDependent()) {
+ if (SS.getScopeRep().isDependent()) {
RevertingTentativeParsingAction PA(*this);
ConsumeAnnotationToken();
ConsumeToken();
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index 8834bf80c4016..1ddc59a5b6fe3 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -1774,9 +1774,9 @@ Parser::TryAnnotateName(CorrectionCandidateCallback *CCC,
/// An Objective-C object type followed by '<' is a specialization of
/// a parameterized class type or a protocol-qualified type.
ParsedType Ty = Classification.getType();
+ QualType T = Actions.GetTypeFromParser(Ty);
if (getLangOpts().ObjC && NextToken().is(tok::less) &&
- (Ty.get()->isObjCObjectType() ||
- Ty.get()->isObjCObjectPointerType())) {
+ (T->isObjCObjectType() || T->isObjCObjectPointerType())) {
// Consume the name.
SourceLocation IdentifierLoc = ConsumeToken();
SourceLocation NewEndLoc;
@@ -2031,11 +2031,12 @@ bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(
if (SS.isNotEmpty()) // it was a C++ qualified type name.
BeginLoc = SS.getBeginLoc();
+ QualType T = Actions.GetTypeFromParser(Ty);
+
/// An Objective-C object type followed by '<' is a specialization of
/// a parameterized class type or a protocol-qualified type.
if (getLangOpts().ObjC && NextToken().is(tok::less) &&
- (Ty.get()->isObjCObjectType() ||
- Ty.get()->isObjCObjectPointerType())) {
+ (T->isObjCObjectType() || T->isObjCObjectPointerType())) {
// Consume the name.
SourceLocation IdentifierLoc = ConsumeToken();
SourceLocation NewEndLoc;
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 7420ba2d461c6..6fcf02fc4ce37 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -223,14 +223,11 @@ static bool hasRecursiveCallInPath(const FunctionDecl *FD, CFGBlock &Block) {
// Skip function calls which are qualified with a templated class.
if (const DeclRefExpr *DRE =
- dyn_cast<DeclRefExpr>(CE->getCallee()->IgnoreParenImpCasts())) {
- if (NestedNameSpecifier *NNS = DRE->getQualifier()) {
- if (NNS->getKind() == NestedNameSpecifier::TypeSpec &&
- isa<TemplateSpecializationType>(NNS->getAsType())) {
+ dyn_cast<DeclRefExpr>(CE->getCallee()->IgnoreParenImpCasts()))
+ if (NestedNameSpecifier NNS = DRE->getQualifier();
+ NNS.getKind() == NestedNameSpecifier::Kind::Type)
+ if (isa_and_nonnull<TemplateSpecializationType>(NNS.getAsType()))
continue;
- }
- }
- }
const CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(CE);
if (!MCE || isa<CXXThisExpr>(MCE->getImplicitObjectArgument()) ||
diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp
index ee5a862c32509..cc385abc3059d 100644
--- a/clang/lib/Sema/DeclSpec.cpp
+++ b/clang/lib/Sema/DeclSpec.cpp
@@ -48,9 +48,9 @@ void UnqualifiedId::setConstructorTemplateId(TemplateIdAnnotation *TemplateId) {
EndLocation = TemplateId->RAngleLoc;
}
-void CXXScopeSpec::Extend(ASTContext &Context, TypeLoc TL,
- SourceLocation ColonColonLoc) {
- Builder.Extend(Context, TL, ColonColonLoc);
+void CXXScopeSpec::Make(ASTContext &Context, TypeLoc TL,
+ SourceLocation ColonColonLoc) {
+ Builder.Make(Context, TL, ColonColonLoc);
if (Range.getBegin().isInvalid())
Range.setBegin(TL.getBeginLoc());
Range.setEnd(ColonColonLoc);
@@ -59,20 +59,7 @@ void CXXScopeSpec::Extend(ASTContext &Context, TypeLoc TL,
"NestedNameSpecifierLoc range computation incorrect");
}
-void CXXScopeSpec::Extend(ASTContext &Context, IdentifierInfo *Identifier,
- SourceLocation IdentifierLoc,
- SourceLocation ColonColonLoc) {
- Builder.Extend(Context, Identifier, IdentifierLoc, ColonColonLoc);
-
- if (Range.getBegin().isInvalid())
- Range.setBegin(IdentifierLoc);
- Range.setEnd(ColonColonLoc);
-
- assert(Range == Builder.getSourceRange() &&
- "NestedNameSpecifierLoc range computation incorrect");
-}
-
-void CXXScopeSpec::Extend(ASTContext &Context, NamespaceDecl *Namespace,
+void CXXScopeSpec::Extend(ASTContext &Context, NamespaceBaseDecl *Namespace,
SourceLocation NamespaceLoc,
SourceLocation ColonColonLoc) {
Builder.Extend(Context, Namespace, NamespaceLoc, ColonColonLoc);
@@ -85,19 +72,6 @@ void CXXScopeSpec::Extend(ASTContext &Context, NamespaceDecl *Namespace,
"NestedNameSpecifierLoc range computation incorrect");
}
-void CXXScopeSpec::Extend(ASTContext &Context, NamespaceAliasDecl *Alias,
- SourceLocation AliasLoc,
- SourceLocation ColonColonLoc) {
- Builder.Extend(Context, Alias, AliasLoc, ColonColonLoc);
-
- if (Range.getBegin().isInvalid())
- Range.setBegin(AliasLoc);
- Range.setEnd(ColonColonLoc);
-
- assert(Range == Builder.getSourceRange() &&
- "NestedNameSpecifierLoc range computation incorrect");
-}
-
void CXXScopeSpec::MakeGlobal(ASTContext &Context,
SourceLocation ColonColonLoc) {
Builder.MakeGlobal(Context, ColonColonLoc);
@@ -121,7 +95,7 @@ void CXXScopeSpec::MakeSuper(ASTContext &Context, CXXRecordDecl *RD,
}
void CXXScopeSpec::MakeTrivial(ASTContext &Context,
- NestedNameSpecifier *Qualifier, SourceRange R) {
+ NestedNameSpecifier Qualifier, SourceRange R) {
Builder.MakeTrivial(Context, Qualifier, R);
Range = R;
}
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
index e5c6220bfb47d..94ea7af88f923 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -313,9 +313,6 @@ TemplateParameterListBuilder::finalizeTemplateArgs(ConceptDecl *CD) {
Builder.Record->getDeclContext()->addDecl(Builder.Template);
Params.clear();
- QualType T = Builder.Template->getInjectedClassNameSpecialization();
- T = AST.getInjectedClassNameType(Builder.Record, T);
-
return Builder;
}
@@ -351,7 +348,7 @@ BuiltinTypeMethodBuilder::BuiltinTypeMethodBuilder(BuiltinTypeDeclBuilder &DB,
ASTContext &AST = DB.SemaRef.getASTContext();
if (IsCtor) {
Name = AST.DeclarationNames.getCXXConstructorName(
- DB.Record->getTypeForDecl()->getCanonicalTypeUnqualified());
+ AST.getCanonicalTagType(DB.Record));
} else {
const IdentifierInfo &II =
AST.Idents.get(NameStr, tok::TokenKind::identifier);
@@ -553,9 +550,9 @@ BuiltinTypeDeclBuilder::BuiltinTypeDeclBuilder(Sema &SemaRef,
return;
}
- Record = CXXRecordDecl::Create(AST, TagDecl::TagKind::Class, HLSLNamespace,
- SourceLocation(), SourceLocation(), &II,
- PrevDecl, true);
+ Record =
+ CXXRecordDecl::Create(AST, TagDecl::TagKind::Class, HLSLNamespace,
+ SourceLocation(), SourceLocation(), &II, PrevDecl);
Record->setImplicit(true);
Record->setLexicalDeclContext(HLSLNamespace);
Record->setHasExternalLexicalStorage();
@@ -570,18 +567,6 @@ BuiltinTypeDeclBuilder::~BuiltinTypeDeclBuilder() {
HLSLNamespace->addDecl(Record);
}
-CXXRecordDecl *BuiltinTypeDeclBuilder::finalizeForwardDeclaration() {
- // Force the QualType to be generated for the record declaration. In most
- // cases this will happen naturally when something uses the type the
- // QualType gets lazily created. Unfortunately, with our injected types if a
- // type isn't used in a translation unit the QualType may not get
- // automatically generated before a PCH is generated. To resolve this we
- // just force that the QualType is generated after we create a forward
- // declaration.
- (void)Record->getASTContext().getRecordType(Record);
- return Record;
-}
-
BuiltinTypeDeclBuilder &
BuiltinTypeDeclBuilder::addMemberVariable(StringRef Name, QualType Type,
llvm::ArrayRef<Attr *> Attrs,
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
index a52e2938104c7..d54b7ddd1adb1 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
@@ -64,7 +64,7 @@ class BuiltinTypeDeclBuilder {
BuiltinTypeDeclBuilder &addSimpleTemplateParams(ArrayRef<StringRef> Names,
ConceptDecl *CD);
- CXXRecordDecl *finalizeForwardDeclaration();
+ CXXRecordDecl *finalizeForwardDeclaration() { return Record; }
BuiltinTypeDeclBuilder &completeDefinition();
BuiltinTypeDeclBuilder &
diff --git a/clang/lib/Sema/HeuristicResolver.cpp b/clang/lib/Sema/HeuristicResolver.cpp
index 6874d30516f8f..9c56dd356421e 100644
--- a/clang/lib/Sema/HeuristicResolver.cpp
+++ b/clang/lib/Sema/HeuristicResolver.cpp
@@ -44,7 +44,7 @@ class HeuristicResolverImpl {
resolveDependentNameType(const DependentNameType *DNT);
std::vector<const NamedDecl *> resolveTemplateSpecializationType(
const DependentTemplateSpecializationType *DTST);
- QualType resolveNestedNameSpecifierToType(const NestedNameSpecifier *NNS);
+ QualType resolveNestedNameSpecifierToType(NestedNameSpecifier NNS);
QualType getPointeeType(QualType T);
std::vector<const NamedDecl *>
lookupDependentName(CXXRecordDecl *RD, DeclarationName Name,
@@ -101,9 +101,8 @@ QualType resolveDeclsToType(const std::vector<const NamedDecl *> &Decls,
ASTContext &Ctx) {
if (Decls.size() != 1) // Names an overload set -- just bail.
return QualType();
- if (const auto *TD = dyn_cast<TypeDecl>(Decls[0])) {
- return Ctx.getTypeDeclType(TD);
- }
+ if (const auto *TD = dyn_cast<TypeDecl>(Decls[0]))
+ return Ctx.getCanonicalTypeDeclType(TD);
if (const auto *VD = dyn_cast<ValueDecl>(Decls[0])) {
return VD->getType();
}
@@ -139,8 +138,7 @@ TagDecl *HeuristicResolverImpl::resolveTypeToTagDecl(QualType QT) {
T = T->getCanonicalTypeInternal().getTypePtr();
}
- if (auto *TT = T->getAs<TagType>()) {
- TagDecl *TD = TT->getDecl();
+ if (auto *TD = T->getAsTagDecl()) {
// Template might not be instantiated yet, fall back to primary template
// in such cases.
if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(TD)) {
@@ -151,11 +149,6 @@ TagDecl *HeuristicResolverImpl::resolveTypeToTagDecl(QualType QT) {
return TD;
}
- if (const auto *ICNT = T->getAs<InjectedClassNameType>())
- T = ICNT->getInjectedSpecializationType().getTypePtrOrNull();
- if (!T)
- return nullptr;
-
TemplateName TN = getReferencedTemplateName(T);
if (TN.isNull())
return nullptr;
@@ -292,7 +285,7 @@ std::vector<const NamedDecl *> HeuristicResolverImpl::resolveMemberExpr(
// an instance method, it's represented as a CXXDependentScopeMemberExpr
// with `this` as the base expression as `X` as the qualifier
// (which could be valid if `X` names a base class after instantiation).
- if (NestedNameSpecifier *NNS = ME->getQualifier()) {
+ if (NestedNameSpecifier NNS = ME->getQualifier()) {
if (QualType QualifierType = resolveNestedNameSpecifierToType(NNS);
!QualifierType.isNull()) {
auto Decls =
@@ -348,7 +341,10 @@ HeuristicResolverImpl::resolveCalleeOfCallExpr(const CallExpr *CE) {
std::vector<const NamedDecl *> HeuristicResolverImpl::resolveUsingValueDecl(
const UnresolvedUsingValueDecl *UUVD) {
- return resolveDependentMember(QualType(UUVD->getQualifier()->getAsType(), 0),
+ NestedNameSpecifier Qualifier = UUVD->getQualifier();
+ if (Qualifier.getKind() != NestedNameSpecifier::Kind::Type)
+ return {};
+ return resolveDependentMember(QualType(Qualifier.getAsType(), 0),
UUVD->getNameInfo().getName(), ValueFilter);
}
@@ -399,23 +395,23 @@ QualType HeuristicResolverImpl::resolveExprToType(const Expr *E) {
}
QualType HeuristicResolverImpl::resolveNestedNameSpecifierToType(
- const NestedNameSpecifier *NNS) {
- if (!NNS)
- return QualType();
-
+ NestedNameSpecifier NNS) {
// The purpose of this function is to handle the dependent (Kind ==
// Identifier) case, but we need to recurse on the prefix because
// that may be dependent as well, so for convenience handle
// the TypeSpec cases too.
- switch (NNS->getKind()) {
- case NestedNameSpecifier::TypeSpec:
- return QualType(NNS->getAsType(), 0);
- case NestedNameSpecifier::Identifier: {
- return resolveDeclsToType(
- resolveDependentMember(
- resolveNestedNameSpecifierToType(NNS->getPrefix()),
- NNS->getAsIdentifier(), TypeFilter),
- Ctx);
+ switch (NNS.getKind()) {
+ case NestedNameSpecifier::Kind::Type: {
+ const auto *T = NNS.getAsType();
+ // FIXME: Should this handle the DependentTemplateSpecializationType as
+ // well?
+ if (const auto *DTN = dyn_cast<DependentNameType>(T))
+ return resolveDeclsToType(
+ resolveDependentMember(
+ resolveNestedNameSpecifierToType(DTN->getQualifier()),
+ DTN->getIdentifier(), TypeFilter),
+ Ctx);
+ return QualType(T, 0);
}
default:
break;
@@ -590,7 +586,7 @@ HeuristicResolver::resolveTemplateSpecializationType(
return HeuristicResolverImpl(Ctx).resolveTemplateSpecializationType(DTST);
}
QualType HeuristicResolver::resolveNestedNameSpecifierToType(
- const NestedNameSpecifier *NNS) const {
+ NestedNameSpecifier NNS) const {
return HeuristicResolverImpl(Ctx).resolveNestedNameSpecifierToType(NNS);
}
std::vector<const NamedDecl *> HeuristicResolver::lookupDependentName(
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 56608e990fd50..48ec4a48b9e63 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -1882,9 +1882,10 @@ class DeferredDiagnosticsEmitter
for (const FieldDecl *FD : RD->fields()) {
QualType FT = FD->getType();
if (const auto *RT = FT->getAs<RecordType>())
- if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl()))
- if (ClassDecl->hasDefinition())
- if (CXXDestructorDecl *MemberDtor = ClassDecl->getDestructor())
+ if (const auto *ClassDecl =
+ dyn_cast<CXXRecordDecl>(RT->getOriginalDecl()))
+ if (const auto *Def = ClassDecl->getDefinition())
+ if (CXXDestructorDecl *MemberDtor = Def->getDestructor())
asImpl().visitUsedDecl(MemberDtor->getLocation(), MemberDtor);
}
@@ -1892,9 +1893,10 @@ class DeferredDiagnosticsEmitter
for (const auto &Base : RD->bases()) {
QualType BaseType = Base.getType();
if (const auto *RT = BaseType->getAs<RecordType>())
- if (const auto *BaseDecl = dyn_cast<CXXRecordDecl>(RT->getDecl()))
- if (BaseDecl->hasDefinition())
- if (CXXDestructorDecl *BaseDtor = BaseDecl->getDestructor())
+ if (const auto *BaseDecl =
+ dyn_cast<CXXRecordDecl>(RT->getOriginalDecl()))
+ if (const auto *Def = BaseDecl->getDefinition())
+ if (CXXDestructorDecl *BaseDtor = Def->getDestructor())
asImpl().visitUsedDecl(BaseDtor->getLocation(), BaseDtor);
}
}
@@ -1907,9 +1909,10 @@ class DeferredDiagnosticsEmitter
VD->needsDestruction(S.Context)) {
QualType VT = VD->getType();
if (const auto *RT = VT->getAs<RecordType>())
- if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl()))
- if (ClassDecl->hasDefinition())
- if (CXXDestructorDecl *Dtor = ClassDecl->getDestructor())
+ if (const auto *ClassDecl =
+ dyn_cast<CXXRecordDecl>(RT->getOriginalDecl()))
+ if (const auto *Def = ClassDecl->getDefinition())
+ if (CXXDestructorDecl *Dtor = Def->getDestructor())
asImpl().visitUsedDecl(Dtor->getLocation(), Dtor);
}
diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp
index 39328b76a10c4..ba560d3c52340 100644
--- a/clang/lib/Sema/SemaAccess.cpp
+++ b/clang/lib/Sema/SemaAccess.cpp
@@ -318,11 +318,8 @@ static AccessResult IsDerivedFromInclusive(const CXXRecordDecl *Derived,
const CXXRecordDecl *RD;
QualType T = I.getType();
- if (const RecordType *RT = T->getAs<RecordType>()) {
- RD = cast<CXXRecordDecl>(RT->getDecl());
- } else if (const InjectedClassNameType *IT
- = T->getAs<InjectedClassNameType>()) {
- RD = IT->getDecl();
+ if (CXXRecordDecl *Rec = T->getAsCXXRecordDecl()) {
+ RD = Rec;
} else {
assert(T->isDependentType() && "non-dependent base wasn't a record?");
OnFailure = AR_dependent;
@@ -443,7 +440,9 @@ static AccessResult MatchesFriend(Sema &S,
const EffectiveContext &EC,
CanQualType Friend) {
if (const RecordType *RT = Friend->getAs<RecordType>())
- return MatchesFriend(S, EC, cast<CXXRecordDecl>(RT->getDecl()));
+ return MatchesFriend(
+ S, EC,
+ cast<CXXRecordDecl>(RT->getOriginalDecl())->getDefinitionOrSelf());
// TODO: we can do better than this
if (Friend->isDependentType())
@@ -671,11 +670,8 @@ struct ProtectedFriendContext {
const CXXRecordDecl *RD;
QualType T = I.getType();
- if (const RecordType *RT = T->getAs<RecordType>()) {
- RD = cast<CXXRecordDecl>(RT->getDecl());
- } else if (const InjectedClassNameType *IT
- = T->getAs<InjectedClassNameType>()) {
- RD = IT->getDecl();
+ if (CXXRecordDecl *Rec = T->getAsCXXRecordDecl()) {
+ RD = Rec;
} else {
assert(T->isDependentType() && "non-dependent base wasn't a record?");
EverDependent = true;
@@ -1072,7 +1068,7 @@ static bool TryDiagnoseProtectedAccess(Sema &S, const EffectiveContext &EC,
// TODO: it would be great to have a fixit here, since this is
// such an obvious error.
S.Diag(D->getLocation(), diag::note_access_protected_restricted_noobject)
- << S.Context.getTypeDeclType(ECRecord);
+ << S.Context.getCanonicalTagType(ECRecord);
return true;
}
@@ -1101,7 +1097,7 @@ static bool TryDiagnoseProtectedAccess(Sema &S, const EffectiveContext &EC,
// Otherwise, use the generic diagnostic.
return S.Diag(D->getLocation(),
diag::note_access_protected_restricted_object)
- << S.Context.getTypeDeclType(ECRecord);
+ << S.Context.getCanonicalTagType(ECRecord);
}
return false;
@@ -1129,7 +1125,8 @@ static void diagnoseBadDirectAccess(Sema &S,
else if (TypedefNameDecl *TND = dyn_cast<TypedefNameDecl>(D))
PrevDecl = TND->getPreviousDecl();
else if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
- if (isa<RecordDecl>(D) && cast<RecordDecl>(D)->isInjectedClassName())
+ if (const auto *RD = dyn_cast<CXXRecordDecl>(TD);
+ RD && RD->isInjectedClassName())
break;
PrevDecl = TD->getPreviousDecl();
}
@@ -1283,10 +1280,10 @@ static void DiagnoseBadAccess(Sema &S, SourceLocation Loc,
NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : nullptr);
S.Diag(Loc, Entity.getDiag())
- << (Entity.getAccess() == AS_protected)
- << (D ? D->getDeclName() : DeclarationName())
- << S.Context.getTypeDeclType(NamingClass)
- << S.Context.getTypeDeclType(DeclaringClass);
+ << (Entity.getAccess() == AS_protected)
+ << (D ? D->getDeclName() : DeclarationName())
+ << S.Context.getCanonicalTagType(NamingClass)
+ << S.Context.getCanonicalTagType(DeclaringClass);
DiagnoseAccessPath(S, EC, Entity);
}
@@ -1639,7 +1636,8 @@ Sema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc,
return AR_accessible;
CXXRecordDecl *NamingClass = Dtor->getParent();
- if (ObjectTy.isNull()) ObjectTy = Context.getTypeDeclType(NamingClass);
+ if (ObjectTy.isNull())
+ ObjectTy = Context.getCanonicalTagType(NamingClass);
AccessTarget Entity(Context, AccessTarget::Member, NamingClass,
DeclAccessPair::make(Dtor, Access),
@@ -1727,7 +1725,7 @@ Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc,
AccessTarget AccessEntity(
Context, AccessTarget::Member, NamingClass,
DeclAccessPair::make(Constructor, Found.getAccess()),
- Context.getTypeDeclType(ObjectClass));
+ Context.getCanonicalTagType(ObjectClass));
AccessEntity.setDiag(PD);
return CheckAccess(*this, UseLoc, AccessEntity);
@@ -1775,7 +1773,7 @@ Sema::CheckStructuredBindingMemberAccess(SourceLocation UseLoc,
return AR_accessible;
AccessTarget Entity(Context, AccessTarget::Member, DecomposedClass, Field,
- Context.getRecordType(DecomposedClass));
+ Context.getCanonicalTagType(DecomposedClass));
Entity.setDiag(diag::err_decomp_decl_inaccessible_field);
return CheckAccess(*this, UseLoc, Entity);
@@ -1789,7 +1787,8 @@ Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc,
return AR_accessible;
const RecordType *RT = ObjectExpr->getType()->castAs<RecordType>();
- CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(RT->getDecl());
+ CXXRecordDecl *NamingClass =
+ cast<CXXRecordDecl>(RT->getOriginalDecl())->getDefinitionOrSelf();
AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
ObjectExpr->getType());
diff --git a/clang/lib/Sema/SemaAvailability.cpp b/clang/lib/Sema/SemaAvailability.cpp
index 8c6a17301fba6..778941c128bdd 100644
--- a/clang/lib/Sema/SemaAvailability.cpp
+++ b/clang/lib/Sema/SemaAvailability.cpp
@@ -102,7 +102,7 @@ Sema::ShouldDiagnoseAvailabilityOfDecl(const NamedDecl *D, std::string *Message,
break;
for (const Type *T = TD->getUnderlyingType().getTypePtr(); /**/; /**/) {
if (auto *TT = dyn_cast<TagType>(T)) {
- D = TT->getDecl();
+ D = TT->getOriginalDecl()->getDefinitionOrSelf();
} else if (isa<SubstTemplateTypeParmType>(T)) {
// A Subst* node represents a use through a template.
// Any uses of the underlying declaration happened through it's template
@@ -1011,7 +1011,7 @@ bool DiagnoseUnguardedAvailability::VisitTypeLoc(TypeLoc Ty) {
return true;
if (const auto *TT = dyn_cast<TagType>(TyPtr)) {
- TagDecl *TD = TT->getDecl();
+ TagDecl *TD = TT->getOriginalDecl()->getDefinitionOrSelf();
DiagnoseDeclAvailability(TD, Range);
} else if (const auto *TD = dyn_cast<TypedefType>(TyPtr)) {
diff --git a/clang/lib/Sema/SemaBPF.cpp b/clang/lib/Sema/SemaBPF.cpp
index 7c00084d62dd9..6428435ed9d2a 100644
--- a/clang/lib/Sema/SemaBPF.cpp
+++ b/clang/lib/Sema/SemaBPF.cpp
@@ -58,10 +58,10 @@ static bool isValidPreserveTypeInfoArg(Expr *Arg) {
// Record type or Enum type.
const Type *Ty = ArgType->getUnqualifiedDesugaredType();
if (const auto *RT = Ty->getAs<RecordType>()) {
- if (!RT->getDecl()->getDeclName().isEmpty())
+ if (!RT->getOriginalDecl()->getDeclName().isEmpty())
return true;
} else if (const auto *ET = Ty->getAs<EnumType>()) {
- if (!ET->getDecl()->getDeclName().isEmpty())
+ if (!ET->getOriginalDecl()->getDeclName().isEmpty())
return true;
}
@@ -105,7 +105,7 @@ static bool isValidPreserveEnumValueArg(Expr *Arg) {
return false;
// The enum value must be supported.
- return llvm::is_contained(ET->getDecl()->enumerators(), Enumerator);
+ return llvm::is_contained(ET->getOriginalDecl()->enumerators(), Enumerator);
}
bool SemaBPF::CheckBPFBuiltinFunctionCall(unsigned BuiltinID,
diff --git a/clang/lib/Sema/SemaCUDA.cpp b/clang/lib/Sema/SemaCUDA.cpp
index 24cb8c369790b..fbf64d3d57050 100644
--- a/clang/lib/Sema/SemaCUDA.cpp
+++ b/clang/lib/Sema/SemaCUDA.cpp
@@ -426,7 +426,8 @@ bool SemaCUDA::inferTargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl,
continue;
}
- CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
+ CXXRecordDecl *BaseClassDecl =
+ cast<CXXRecordDecl>(BaseType->getOriginalDecl())->getDefinitionOrSelf();
Sema::SpecialMemberOverloadResult SMOR =
SemaRef.LookupSpecialMember(BaseClassDecl, CSM,
/* ConstArg */ ConstRHS,
@@ -471,7 +472,9 @@ bool SemaCUDA::inferTargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl,
continue;
}
- CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(FieldType->getDecl());
+ CXXRecordDecl *FieldRecDecl =
+ cast<CXXRecordDecl>(FieldType->getOriginalDecl())
+ ->getDefinitionOrSelf();
Sema::SpecialMemberOverloadResult SMOR =
SemaRef.LookupSpecialMember(FieldRecDecl, CSM,
/* ConstArg */ ConstRHS && !F->isMutable(),
diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp
index ab83f625d2849..fefcfdcdb3fd4 100644
--- a/clang/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp
@@ -28,24 +28,21 @@ static CXXRecordDecl *getCurrentInstantiationOf(QualType T,
if (T.isNull())
return nullptr;
- const Type *Ty = T->getCanonicalTypeInternal().getTypePtr();
- if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
- CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordTy->getDecl());
- if (Record->isCurrentInstantiation(CurContext))
- return Record;
-
- return nullptr;
- } else if (isa<InjectedClassNameType>(Ty))
- return cast<InjectedClassNameType>(Ty)->getDecl();
- else
+ const TagType *TagTy = dyn_cast<TagType>(T->getCanonicalTypeInternal());
+ if (!isa_and_present<RecordType, InjectedClassNameType>(TagTy))
return nullptr;
+ auto *RD =
+ cast<CXXRecordDecl>(TagTy->getOriginalDecl())->getDefinitionOrSelf();
+ if (isa<InjectedClassNameType>(TagTy) ||
+ RD->isCurrentInstantiation(CurContext))
+ return RD;
+ return nullptr;
}
DeclContext *Sema::computeDeclContext(QualType T) {
if (!T->isDependentType())
- if (const TagType *Tag = T->getAs<TagType>())
- return Tag->getDecl();
-
+ if (auto *D = T->getAsTagDecl())
+ return D;
return ::getCurrentInstantiationOf(T, CurContext);
}
@@ -54,18 +51,17 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS,
if (!SS.isSet() || SS.isInvalid())
return nullptr;
- NestedNameSpecifier *NNS = SS.getScopeRep();
- if (NNS->isDependent()) {
+ NestedNameSpecifier NNS = SS.getScopeRep();
+ if (NNS.isDependent()) {
// If this nested-name-specifier refers to the current
// instantiation, return its DeclContext.
if (CXXRecordDecl *Record = getCurrentInstantiationOf(NNS))
return Record;
if (EnteringContext) {
- const Type *NNSType = NNS->getAsType();
- if (!NNSType) {
+ if (NNS.getKind() != NestedNameSpecifier::Kind::Type)
return nullptr;
- }
+ const Type *NNSType = NNS.getAsType();
// Look through type alias templates, per C++0x [temp.dep.type]p1.
NNSType = Context.getCanonicalType(NNSType);
@@ -118,41 +114,39 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS,
// If the type of the nested name specifier is the same as the
// injected class name of the named class template, we're entering
// into that class template definition.
- QualType Injected =
- ClassTemplate->getInjectedClassNameSpecialization();
+ CanQualType Injected =
+ ClassTemplate->getCanonicalInjectedSpecializationType(Context);
if (Context.hasSameType(Injected, QualType(SpecType, 0)))
return ClassTemplate->getTemplatedDecl();
}
- } else if (const RecordType *RecordT = NNSType->getAs<RecordType>()) {
+ } else if (const auto *RecordT = dyn_cast<RecordType>(NNSType)) {
// The nested name specifier refers to a member of a class template.
- return RecordT->getDecl();
+ return RecordT->getOriginalDecl()->getDefinitionOrSelf();
}
}
return nullptr;
}
- switch (NNS->getKind()) {
- case NestedNameSpecifier::Identifier:
- llvm_unreachable("Dependent nested-name-specifier has no DeclContext");
-
- case NestedNameSpecifier::Namespace:
- return NNS->getAsNamespace();
-
- case NestedNameSpecifier::NamespaceAlias:
- return NNS->getAsNamespaceAlias()->getNamespace();
+ switch (NNS.getKind()) {
+ case NestedNameSpecifier::Kind::Namespace:
+ return const_cast<NamespaceDecl *>(
+ NNS.getAsNamespaceAndPrefix().Namespace->getNamespace());
- case NestedNameSpecifier::TypeSpec: {
- const TagType *Tag = NNS->getAsType()->getAs<TagType>();
- assert(Tag && "Non-tag type in nested-name-specifier");
- return Tag->getDecl();
+ case NestedNameSpecifier::Kind::Type: {
+ auto *TD = NNS.getAsType()->getAsTagDecl();
+ assert(TD && "Non-tag type in nested-name-specifier");
+ return TD;
}
- case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Kind::Global:
return Context.getTranslationUnitDecl();
- case NestedNameSpecifier::Super:
- return NNS->getAsRecordDecl();
+ case NestedNameSpecifier::Kind::Super:
+ return NNS.getAsSuper();
+
+ case NestedNameSpecifier::Kind::Null:
+ llvm_unreachable("unexpected null nested name specifier");
}
llvm_unreachable("Invalid NestedNameSpecifier::Kind!");
@@ -162,17 +156,17 @@ bool Sema::isDependentScopeSpecifier(const CXXScopeSpec &SS) {
if (!SS.isSet() || SS.isInvalid())
return false;
- return SS.getScopeRep()->isDependent();
+ return SS.getScopeRep().isDependent();
}
-CXXRecordDecl *Sema::getCurrentInstantiationOf(NestedNameSpecifier *NNS) {
+CXXRecordDecl *Sema::getCurrentInstantiationOf(NestedNameSpecifier NNS) {
assert(getLangOpts().CPlusPlus && "Only callable in C++");
- assert(NNS->isDependent() && "Only dependent nested-name-specifier allowed");
+ assert(NNS.isDependent() && "Only dependent nested-name-specifier allowed");
- if (!NNS->getAsType())
+ if (NNS.getKind() != NestedNameSpecifier::Kind::Type)
return nullptr;
- QualType T = QualType(NNS->getAsType(), 0);
+ QualType T = QualType(NNS.getAsType(), 0);
return ::getCurrentInstantiationOf(T, CurContext);
}
@@ -198,8 +192,7 @@ bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS,
return false;
// Grab the tag definition, if there is one.
- QualType type = Context.getTypeDeclType(tag);
- tag = type->getAsTagDecl();
+ tag = tag->getDefinitionOrSelf();
// If we're currently defining this type, then lookup into the
// type is okay: don't complain that it isn't complete yet.
@@ -210,7 +203,8 @@ bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS,
if (loc.isInvalid()) loc = SS.getRange().getBegin();
// The type must be complete.
- if (RequireCompleteType(loc, type, diag::err_incomplete_nested_name_spec,
+ if (RequireCompleteType(loc, Context.getCanonicalTagType(tag),
+ diag::err_incomplete_nested_name_spec,
SS.getRange())) {
SS.SetInvalid(SS.getRange());
return true;
@@ -262,10 +256,10 @@ bool Sema::RequireCompleteEnumDecl(EnumDecl *EnumD, SourceLocation L,
if (SS) {
Diag(L, diag::err_incomplete_nested_name_spec)
- << QualType(EnumD->getTypeForDecl(), 0) << SS->getRange();
+ << Context.getCanonicalTagType(EnumD) << SS->getRange();
SS->SetInvalid(SS->getRange());
} else {
- Diag(L, diag::err_incomplete_enum) << QualType(EnumD->getTypeForDecl(), 0);
+ Diag(L, diag::err_incomplete_enum) << Context.getCanonicalTagType(EnumD);
Diag(EnumD->getLocation(), diag::note_declared_at);
}
@@ -327,9 +321,6 @@ bool Sema::isAcceptableNestedNameSpecifier(const NamedDecl *SD,
// Determine whether we have a class (or, in C++11, an enum) or
// a typedef thereof. If so, build the nested-name-specifier.
- QualType T = Context.getTypeDeclType(cast<TypeDecl>(SD));
- if (T->isDependentType())
- return true;
if (const TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) {
if (TD->getUnderlyingType()->isRecordType())
return true;
@@ -347,32 +338,42 @@ bool Sema::isAcceptableNestedNameSpecifier(const NamedDecl *SD,
if (IsExtension)
*IsExtension = true;
}
+ if (auto *TD = dyn_cast<TagDecl>(SD)) {
+ if (TD->isDependentType())
+ return true;
+ } else if (Context.getCanonicalTypeDeclType(cast<TypeDecl>(SD))
+ ->isDependentType()) {
+ return true;
+ }
return false;
}
-NamedDecl *Sema::FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS) {
- if (!S || !NNS)
+NamedDecl *Sema::FindFirstQualifierInScope(Scope *S, NestedNameSpecifier NNS) {
+ if (!S)
return nullptr;
- while (NNS->getPrefix())
- NNS = NNS->getPrefix();
-
- if (NNS->getKind() != NestedNameSpecifier::Identifier)
- return nullptr;
+ while (NNS.getKind() == NestedNameSpecifier::Kind::Type) {
+ const Type *T = NNS.getAsType();
+ if ((NNS = T->getPrefix()))
+ continue;
- LookupResult Found(*this, NNS->getAsIdentifier(), SourceLocation(),
- LookupNestedNameSpecifierName);
- LookupName(Found, S);
- assert(!Found.isAmbiguous() && "Cannot handle ambiguities here yet");
+ const auto *DNT = dyn_cast<DependentNameType>(T);
+ if (!DNT)
+ break;
- if (!Found.isSingleResult())
- return nullptr;
+ LookupResult Found(*this, DNT->getIdentifier(), SourceLocation(),
+ LookupNestedNameSpecifierName);
+ LookupName(Found, S);
+ assert(!Found.isAmbiguous() && "Cannot handle ambiguities here yet");
- NamedDecl *Result = Found.getFoundDecl();
- if (isAcceptableNestedNameSpecifier(Result))
- return Result;
+ if (!Found.isSingleResult())
+ return nullptr;
+ NamedDecl *Result = Found.getFoundDecl();
+ if (isAcceptableNestedNameSpecifier(Result))
+ return Result;
+ }
return nullptr;
}
@@ -496,7 +497,18 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo,
// base object type or prior nested-name-specifier, so this
// nested-name-specifier refers to an unknown specialization. Just build
// a dependent nested-name-specifier.
- SS.Extend(Context, IdInfo.Identifier, IdInfo.IdentifierLoc, IdInfo.CCLoc);
+
+ TypeLocBuilder TLB;
+
+ QualType DTN = Context.getDependentNameType(
+ ElaboratedTypeKeyword::None, SS.getScopeRep(), IdInfo.Identifier);
+ auto DTNL = TLB.push<DependentNameTypeLoc>(DTN);
+ DTNL.setElaboratedKeywordLoc(SourceLocation());
+ DTNL.setNameLoc(IdInfo.IdentifierLoc);
+ DTNL.setQualifierLoc(SS.getWithLocInContext(Context));
+
+ SS.clear();
+ SS.Make(Context, TLB.getTypeLocInContext(Context, DTN), IdInfo.CCLoc);
return false;
}
@@ -602,8 +614,8 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo,
OuterDecl->getCanonicalDecl() != SD->getCanonicalDecl() &&
(!isa<TypeDecl>(OuterDecl) || !isa<TypeDecl>(SD) ||
!Context.hasSameType(
- Context.getTypeDeclType(cast<TypeDecl>(OuterDecl)),
- Context.getTypeDeclType(cast<TypeDecl>(SD))))) {
+ Context.getCanonicalTypeDeclType(cast<TypeDecl>(OuterDecl)),
+ Context.getCanonicalTypeDeclType(cast<TypeDecl>(SD))))) {
if (ErrorRecoveryLookup)
return true;
@@ -616,7 +628,7 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo,
// Fall through so that we'll pick the name we found in the object
// type, since that's probably what the user wanted anyway.
- }
+ }
}
if (auto *TD = dyn_cast_or_null<TypedefNameDecl>(SD))
@@ -640,50 +652,44 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo,
return false;
}
- QualType T =
- Context.getTypeDeclType(cast<TypeDecl>(SD->getUnderlyingDecl()));
-
- if (T->isEnumeralType())
+ const auto *TD = cast<TypeDecl>(SD->getUnderlyingDecl());
+ if (isa<EnumDecl>(TD))
Diag(IdInfo.IdentifierLoc, diag::warn_cxx98_compat_enum_nested_name_spec);
+ QualType T;
TypeLocBuilder TLB;
if (const auto *USD = dyn_cast<UsingShadowDecl>(SD)) {
- T = Context.getUsingType(USD, T);
- TLB.pushTypeSpec(T).setNameLoc(IdInfo.IdentifierLoc);
- } else if (isa<InjectedClassNameType>(T)) {
- InjectedClassNameTypeLoc InjectedTL
- = TLB.push<InjectedClassNameTypeLoc>(T);
- InjectedTL.setNameLoc(IdInfo.IdentifierLoc);
- } else if (isa<RecordType>(T)) {
- RecordTypeLoc RecordTL = TLB.push<RecordTypeLoc>(T);
- RecordTL.setNameLoc(IdInfo.IdentifierLoc);
- } else if (isa<TypedefType>(T)) {
- TypedefTypeLoc TypedefTL = TLB.push<TypedefTypeLoc>(T);
- TypedefTL.setNameLoc(IdInfo.IdentifierLoc);
- } else if (isa<EnumType>(T)) {
- EnumTypeLoc EnumTL = TLB.push<EnumTypeLoc>(T);
- EnumTL.setNameLoc(IdInfo.IdentifierLoc);
- } else if (isa<TemplateTypeParmType>(T)) {
- TemplateTypeParmTypeLoc TemplateTypeTL
- = TLB.push<TemplateTypeParmTypeLoc>(T);
- TemplateTypeTL.setNameLoc(IdInfo.IdentifierLoc);
- } else if (isa<UnresolvedUsingType>(T)) {
- UnresolvedUsingTypeLoc UnresolvedTL
- = TLB.push<UnresolvedUsingTypeLoc>(T);
- UnresolvedTL.setNameLoc(IdInfo.IdentifierLoc);
- } else if (isa<SubstTemplateTypeParmType>(T)) {
- SubstTemplateTypeParmTypeLoc TL
- = TLB.push<SubstTemplateTypeParmTypeLoc>(T);
- TL.setNameLoc(IdInfo.IdentifierLoc);
- } else if (isa<SubstTemplateTypeParmPackType>(T)) {
- SubstTemplateTypeParmPackTypeLoc TL
- = TLB.push<SubstTemplateTypeParmPackTypeLoc>(T);
- TL.setNameLoc(IdInfo.IdentifierLoc);
+ T = Context.getUsingType(ElaboratedTypeKeyword::None, SS.getScopeRep(),
+ USD);
+ TLB.push<UsingTypeLoc>(T).set(/*ElaboratedKeywordLoc=*/SourceLocation(),
+ SS.getWithLocInContext(Context),
+ IdInfo.IdentifierLoc);
+ } else if (const auto *Tag = dyn_cast<TagDecl>(TD)) {
+ T = Context.getTagType(ElaboratedTypeKeyword::None, SS.getScopeRep(), Tag,
+ /*OwnsTag=*/false);
+ auto TTL = TLB.push<TagTypeLoc>(T);
+ TTL.setElaboratedKeywordLoc(SourceLocation());
+ TTL.setQualifierLoc(SS.getWithLocInContext(SemaRef.Context));
+ TTL.setNameLoc(IdInfo.IdentifierLoc);
+ } else if (auto *TN = dyn_cast<TypedefNameDecl>(TD)) {
+ T = Context.getTypedefType(ElaboratedTypeKeyword::None, SS.getScopeRep(),
+ TN);
+ TLB.push<TypedefTypeLoc>(T).set(/*ElaboratedKeywordLoc=*/SourceLocation(),
+ SS.getWithLocInContext(SemaRef.Context),
+ IdInfo.IdentifierLoc);
+ } else if (auto *UD = dyn_cast<UnresolvedUsingTypenameDecl>(TD)) {
+ T = Context.getUnresolvedUsingType(ElaboratedTypeKeyword::None,
+ SS.getScopeRep(), UD);
+ TLB.push<UnresolvedUsingTypeLoc>(T).set(
+ /*ElaboratedKeywordLoc=*/SourceLocation(),
+ SS.getWithLocInContext(SemaRef.Context), IdInfo.IdentifierLoc);
} else {
- llvm_unreachable("Unhandled TypeDecl node in nested-name-specifier");
+ assert(SS.isEmpty());
+ T = Context.getTypeDeclType(TD);
+ TLB.pushTypeSpec(T).setNameLoc(IdInfo.IdentifierLoc);
}
-
- SS.Extend(Context, TLB.getTypeLocInContext(Context, T), IdInfo.CCLoc);
+ SS.clear();
+ SS.Make(Context, TLB.getTypeLocInContext(Context, T), IdInfo.CCLoc);
return false;
}
@@ -725,16 +731,34 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo,
Diag(IdInfo.IdentifierLoc,
diag::ext_undeclared_unqual_id_with_dependent_base)
<< IdInfo.Identifier << ContainingClass;
+
+ TypeLocBuilder TLB;
+
// Fake up a nested-name-specifier that starts with the
// injected-class-name of the enclosing class.
- QualType T = Context.getTypeDeclType(ContainingClass);
- TypeLocBuilder TLB;
- TLB.pushTrivial(Context, T, IdInfo.IdentifierLoc);
- SS.Extend(Context, TLB.getTypeLocInContext(Context, T),
- IdInfo.IdentifierLoc);
- // Add the identifier to form a dependent name.
- SS.Extend(Context, IdInfo.Identifier, IdInfo.IdentifierLoc,
- IdInfo.CCLoc);
+ // FIXME: This should be done as part of an adjustment, so that this
+ // doesn't get confused with something written in source.
+ QualType Result =
+ Context.getTagType(ElaboratedTypeKeyword::None, SS.getScopeRep(),
+ ContainingClass, /*OwnsTag=*/false);
+ auto TTL = TLB.push<TagTypeLoc>(Result);
+ TTL.setElaboratedKeywordLoc(SourceLocation());
+ TTL.setQualifierLoc(SS.getWithLocInContext(Context));
+ TTL.setNameLoc(IdInfo.IdentifierLoc);
+ SS.Make(Context, TLB.getTypeLocInContext(Context, Result),
+ SourceLocation());
+
+ TLB.clear();
+
+ // Form a DependentNameType.
+ QualType DTN = Context.getDependentNameType(
+ ElaboratedTypeKeyword::None, SS.getScopeRep(), IdInfo.Identifier);
+ auto DTNL = TLB.push<DependentNameTypeLoc>(DTN);
+ DTNL.setElaboratedKeywordLoc(SourceLocation());
+ DTNL.setNameLoc(IdInfo.IdentifierLoc);
+ DTNL.setQualifierLoc(SS.getWithLocInContext(Context));
+ SS.clear();
+ SS.Make(Context, TLB.getTypeLocInContext(Context, DTN), IdInfo.CCLoc);
return false;
}
}
@@ -742,8 +766,19 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo,
if (!Found.empty()) {
if (TypeDecl *TD = Found.getAsSingle<TypeDecl>()) {
+ QualType T;
+ if (auto *TN = dyn_cast<TypedefNameDecl>(TD)) {
+ T = Context.getTypedefType(ElaboratedTypeKeyword::None,
+ SS.getScopeRep(), TN);
+ } else {
+ // FIXME: Enumerate the possibilities here.
+ assert(!isa<TagDecl>(TD));
+ assert(SS.isEmpty());
+ T = Context.getTypeDeclType(TD);
+ }
+
Diag(IdInfo.IdentifierLoc, diag::err_expected_class_or_namespace)
- << Context.getTypeDeclType(TD) << getLangOpts().CPlusPlus;
+ << T << getLangOpts().CPlusPlus;
} else if (Found.getAsSingle<TemplateDecl>()) {
ParsedType SuggestedType;
DiagnoseUnknownTypeName(IdInfo.Identifier, IdInfo.IdentifierLoc, S, &SS,
@@ -789,17 +824,19 @@ bool Sema::ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS,
if (T.isNull())
return true;
- if (!T->isDependentType() && !T->getAs<TagType>()) {
+ if (!T->isDependentType() && !isa<TagType>(T.getCanonicalType())) {
Diag(DS.getTypeSpecTypeLoc(), diag::err_expected_class_or_namespace)
<< T << getLangOpts().CPlusPlus;
return true;
}
+ assert(SS.isEmpty());
+
TypeLocBuilder TLB;
DecltypeTypeLoc DecltypeTL = TLB.push<DecltypeTypeLoc>(T);
DecltypeTL.setDecltypeLoc(DS.getTypeSpecTypeLoc());
DecltypeTL.setRParenLoc(DS.getTypeofParensRange().getEnd());
- SS.Extend(Context, TLB.getTypeLocInContext(Context, T), ColonColonLoc);
+ SS.Make(Context, TLB.getTypeLocInContext(Context, T), ColonColonLoc);
return false;
}
@@ -815,13 +852,15 @@ bool Sema::ActOnCXXNestedNameSpecifierIndexedPack(CXXScopeSpec &SS,
if (Type.isNull())
return true;
+ assert(SS.isEmpty());
+
TypeLocBuilder TLB;
TLB.pushTrivial(getASTContext(),
cast<PackIndexingType>(Type.getTypePtr())->getPattern(),
DS.getBeginLoc());
PackIndexingTypeLoc PIT = TLB.push<PackIndexingTypeLoc>(Type);
PIT.setEllipsisLoc(DS.getEllipsisLoc());
- SS.Extend(Context, TLB.getTypeLocInContext(Context, Type), ColonColonLoc);
+ SS.Make(Context, TLB.getTypeLocInContext(Context, Type), ColonColonLoc);
return false;
}
@@ -861,7 +900,7 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
assert(DTN->getQualifier() == SS.getScopeRep());
QualType T = Context.getDependentTemplateSpecializationType(
ElaboratedTypeKeyword::None,
- {/*Qualifier=*/nullptr, DTN->getName().getIdentifier(),
+ {SS.getScopeRep(), DTN->getName().getIdentifier(),
TemplateKWLoc.isValid()},
TemplateArgs.arguments());
@@ -870,7 +909,7 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
DependentTemplateSpecializationTypeLoc SpecTL
= Builder.push<DependentTemplateSpecializationTypeLoc>(T);
SpecTL.setElaboratedKeywordLoc(SourceLocation());
- SpecTL.setQualifierLoc(NestedNameSpecifierLoc());
+ SpecTL.setQualifierLoc(SS.getWithLocInContext(Context));
SpecTL.setTemplateKeywordLoc(TemplateKWLoc);
SpecTL.setTemplateNameLoc(TemplateNameLoc);
SpecTL.setLAngleLoc(LAngleLoc);
@@ -878,7 +917,8 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
- SS.Extend(Context, Builder.getTypeLocInContext(Context, T), CCLoc);
+ SS.clear();
+ SS.Make(Context, Builder.getTypeLocInContext(Context, T), CCLoc);
return false;
}
@@ -903,30 +943,28 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
// We were able to resolve the template name to an actual template.
// Build an appropriate nested-name-specifier.
- QualType T = CheckTemplateIdType(Template, TemplateNameLoc, TemplateArgs);
+ QualType T = CheckTemplateIdType(ElaboratedTypeKeyword::None, Template,
+ TemplateNameLoc, TemplateArgs);
if (T.isNull())
return true;
// Alias template specializations can produce types which are not valid
// nested name specifiers.
- if (!T->isDependentType() && !T->getAs<TagType>()) {
+ if (!T->isDependentType() && !isa<TagType>(T.getCanonicalType())) {
Diag(TemplateNameLoc, diag::err_nested_name_spec_non_tag) << T;
NoteAllFoundTemplates(Template);
return true;
}
// Provide source-location information for the template specialization type.
- TypeLocBuilder Builder;
- TemplateSpecializationTypeLoc SpecTL
- = Builder.push<TemplateSpecializationTypeLoc>(T);
- SpecTL.setTemplateKeywordLoc(TemplateKWLoc);
- SpecTL.setTemplateNameLoc(TemplateNameLoc);
- SpecTL.setLAngleLoc(LAngleLoc);
- SpecTL.setRAngleLoc(RAngleLoc);
- for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
- SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
-
- SS.Extend(Context, Builder.getTypeLocInContext(Context, T), CCLoc);
+ TypeLocBuilder TLB;
+ TLB.push<TemplateSpecializationTypeLoc>(T).set(
+ /*ElaboratedKeywordLoc=*/SourceLocation(),
+ SS.getWithLocInContext(Context), TemplateKWLoc, TemplateNameLoc,
+ TemplateArgs);
+
+ SS.clear();
+ SS.Make(Context, TLB.getTypeLocInContext(Context, T), CCLoc);
return false;
}
@@ -934,7 +972,7 @@ namespace {
/// A structure that stores a nested-name-specifier annotation,
/// including both the nested-name-specifier
struct NestedNameSpecifierAnnotation {
- NestedNameSpecifier *NNS;
+ NestedNameSpecifier NNS = std::nullopt;
};
}
@@ -973,8 +1011,6 @@ bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
if (isa<ObjCContainerDecl>(CurContext) || isa<ObjCMethodDecl>(CurContext))
return false;
- NestedNameSpecifier *Qualifier = SS.getScopeRep();
-
// There are only two places a well-formed program may qualify a
// declarator: first, when defining a namespace or class member
// out-of-line, and second, when naming an explicitly-qualified
@@ -989,19 +1025,20 @@ bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
// granting friendship.
// i.e. we don't push a scope unless it's a class member.
- switch (Qualifier->getKind()) {
- case NestedNameSpecifier::Global:
- case NestedNameSpecifier::Namespace:
- case NestedNameSpecifier::NamespaceAlias:
+ switch (SS.getScopeRep().getKind()) {
+ case NestedNameSpecifier::Kind::Global:
+ case NestedNameSpecifier::Kind::Namespace:
// These are always namespace scopes. We never want to enter a
// namespace scope from anything but a file context.
return CurContext->getRedeclContext()->isFileContext();
- case NestedNameSpecifier::Identifier:
- case NestedNameSpecifier::TypeSpec:
- case NestedNameSpecifier::Super:
+ case NestedNameSpecifier::Kind::Type:
+ case NestedNameSpecifier::Kind::Super:
// These are never namespace scopes.
return true;
+
+ case NestedNameSpecifier::Kind::Null:
+ llvm_unreachable("unexpected null nested name specifier");
}
llvm_unreachable("Invalid NestedNameSpecifier::Kind!");
diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp
index e27ed8fd4de14..adcb0df6213c5 100644
--- a/clang/lib/Sema/SemaCast.cpp
+++ b/clang/lib/Sema/SemaCast.cpp
@@ -964,7 +964,7 @@ void CastOperation::CheckDynamicCast() {
}
// C++ 5.2.7p6: Otherwise, v shall be [polymorphic].
- const RecordDecl *SrcDecl = SrcRecord->getDecl()->getDefinition();
+ const RecordDecl *SrcDecl = SrcRecord->getOriginalDecl()->getDefinition();
assert(SrcDecl && "Definition missing");
if (!cast<CXXRecordDecl>(SrcDecl)->isPolymorphic()) {
Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_polymorphic)
@@ -1455,7 +1455,7 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
// converted to an integral type. [...] A value of a scoped enumeration type
// can also be explicitly converted to a floating-point type [...].
if (const EnumType *Enum = SrcType->getAs<EnumType>()) {
- if (Enum->getDecl()->isScoped()) {
+ if (Enum->getOriginalDecl()->isScoped()) {
if (DestType->isBooleanType()) {
Kind = CK_IntegralToBoolean;
return TC_Success;
@@ -1487,8 +1487,8 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
// [expr.static.cast]p10 If the enumeration type has a fixed underlying
// type, the value is first converted to that type by integral conversion
const EnumType *Enum = DestType->castAs<EnumType>();
- Kind = Enum->getDecl()->isFixed() &&
- Enum->getDecl()->getIntegerType()->isBooleanType()
+ const EnumDecl *ED = Enum->getOriginalDecl()->getDefinitionOrSelf();
+ Kind = ED->isFixed() && ED->getIntegerType()->isBooleanType()
? CK_IntegralToBoolean
: CK_IntegralCast;
return TC_Success;
@@ -1858,7 +1858,7 @@ TryCastResult TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr,
FoundOverload)) {
CXXMethodDecl *M = cast<CXXMethodDecl>(Fn);
SrcType = Self.Context.getMemberPointerType(
- Fn->getType(), /*Qualifier=*/nullptr, M->getParent());
+ Fn->getType(), /*Qualifier=*/std::nullopt, M->getParent());
WasOverloadedFunction = true;
}
}
@@ -2104,9 +2104,9 @@ void Sema::CheckCompatibleReinterpretCast(QualType SrcType, QualType DestType,
return;
}
// or one of the types is a tag type.
- if (SrcTy->getAs<TagType>() || DestTy->getAs<TagType>()) {
+ if (isa<TagType>(SrcTy.getCanonicalType()) ||
+ isa<TagType>(DestTy.getCanonicalType()))
return;
- }
// FIXME: Scoped enums?
if ((SrcTy->isUnsignedIntegerType() && DestTy->isSignedIntegerType()) ||
@@ -3099,27 +3099,26 @@ void CastOperation::CheckCStyleCast() {
if (!DestType->isScalarType() && !DestType->isVectorType() &&
!DestType->isMatrixType()) {
- const RecordType *DestRecordTy = DestType->getAs<RecordType>();
-
- if (DestRecordTy && Self.Context.hasSameUnqualifiedType(DestType, SrcType)){
- // GCC struct/union extension: allow cast to self.
- Self.Diag(OpRange.getBegin(), diag::ext_typecheck_cast_nonscalar)
- << DestType << SrcExpr.get()->getSourceRange();
- Kind = CK_NoOp;
- return;
- }
-
- // GCC's cast to union extension.
- if (DestRecordTy && DestRecordTy->getDecl()->isUnion()) {
- RecordDecl *RD = DestRecordTy->getDecl();
- if (CastExpr::getTargetFieldForToUnionCast(RD, SrcType)) {
- Self.Diag(OpRange.getBegin(), diag::ext_typecheck_cast_to_union)
- << SrcExpr.get()->getSourceRange();
- Kind = CK_ToUnion;
+ if (const RecordType *DestRecordTy = DestType->getAs<RecordType>()) {
+ if (Self.Context.hasSameUnqualifiedType(DestType, SrcType)) {
+ // GCC struct/union extension: allow cast to self.
+ Self.Diag(OpRange.getBegin(), diag::ext_typecheck_cast_nonscalar)
+ << DestType << SrcExpr.get()->getSourceRange();
+ Kind = CK_NoOp;
return;
- } else {
+ }
+
+ // GCC's cast to union extension.
+ if (RecordDecl *RD = DestRecordTy->getOriginalDecl(); RD->isUnion()) {
+ if (CastExpr::getTargetFieldForToUnionCast(RD->getDefinitionOrSelf(),
+ SrcType)) {
+ Self.Diag(OpRange.getBegin(), diag::ext_typecheck_cast_to_union)
+ << SrcExpr.get()->getSourceRange();
+ Kind = CK_ToUnion;
+ return;
+ }
Self.Diag(OpRange.getBegin(), diag::err_typecheck_cast_to_union_no_type)
- << SrcType << SrcExpr.get()->getSourceRange();
+ << SrcType << SrcExpr.get()->getSourceRange();
SrcExpr = ExprError();
return;
}
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index dd5b710d7e1d4..f4daa8f506ccf 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -603,7 +603,7 @@ struct BuiltinDumpStructGenerator {
bool dumpUnnamedRecord(const RecordDecl *RD, Expr *E, unsigned Depth) {
Expr *IndentLit = getIndentString(Depth);
- Expr *TypeLit = getTypeString(S.Context.getRecordType(RD));
+ Expr *TypeLit = getTypeString(S.Context.getCanonicalTagType(RD));
if (IndentLit ? callPrintFunction("%s%s", {IndentLit, TypeLit})
: callPrintFunction("%s", {TypeLit}))
return true;
@@ -2288,7 +2288,7 @@ static ExprResult BuiltinInvoke(Sema &S, CallExpr *TheCall) {
return ExprError();
}
- const Type *MemPtrClass = MPT->getQualifier()->getAsType();
+ const Type *MemPtrClass = MPT->getQualifier().getAsType();
QualType ObjectT = Args[1]->getType();
if (MPT->isMemberDataPointer() && S.checkArgCount(TheCall, 2))
@@ -3315,7 +3315,9 @@ static bool CheckNonNullExpr(Sema &S, const Expr *Expr) {
// As a special case, transparent unions initialized with zero are
// considered null for the purposes of the nonnull attribute.
if (const RecordType *UT = Expr->getType()->getAsUnionType();
- UT && UT->getDecl()->hasAttr<TransparentUnionAttr>()) {
+ UT && UT->getOriginalDecl()
+ ->getMostRecentDecl()
+ ->hasAttr<TransparentUnionAttr>()) {
if (const auto *CLE = dyn_cast<CompoundLiteralExpr>(Expr))
if (const auto *ILE = dyn_cast<InitListExpr>(CLE->getInitializer()))
Expr = ILE->getInit(0);
@@ -5172,7 +5174,9 @@ bool Sema::BuiltinVAStart(unsigned BuiltinID, CallExpr *TheCall) {
return false;
if (!Type->isEnumeralType())
return true;
- const EnumDecl *ED = Type->castAs<EnumType>()->getDecl();
+ const EnumDecl *ED = Type->castAs<EnumType>()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf();
return !(ED &&
Context.typesAreCompatible(ED->getPromotionType(), Type));
}()) {
@@ -7786,8 +7790,11 @@ CXXRecordMembersNamed(StringRef Name, Sema &S, QualType Ty) {
if (!RT)
return Results;
- const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
- if (!RD || !RD->getDefinition())
+ CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getOriginalDecl());
+ if (!RD)
+ return Results;
+ RD = RD->getDefinition();
+ if (!RD)
return Results;
LookupResult R(S, &S.Context.Idents.get(Name), SourceLocation(),
@@ -7796,7 +7803,7 @@ CXXRecordMembersNamed(StringRef Name, Sema &S, QualType Ty) {
// We just need to include all members of the right kind turned up by the
// filter, at this point.
- if (S.LookupQualifiedName(R, RT->getDecl()))
+ if (S.LookupQualifiedName(R, RD))
for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
NamedDecl *decl = (*I)->getUnderlyingDecl();
if (MemberKind *FK = dyn_cast<MemberKind>(decl))
@@ -8323,7 +8330,8 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
bool IsScopedEnum = false;
QualType IntendedTy = ExprTy;
if (auto EnumTy = ExprTy->getAs<EnumType>()) {
- IntendedTy = EnumTy->getDecl()->getIntegerType();
+ IntendedTy =
+ EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
if (EnumTy->isUnscopedEnumerationType()) {
ExprTy = IntendedTy;
// This controls whether we're talking about the underlying type or not,
@@ -8359,7 +8367,9 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
NamedDecl *ND = Result.getFoundDecl();
if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(ND))
if (TD->getUnderlyingType() == IntendedTy)
- IntendedTy = S.Context.getTypedefType(TD);
+ IntendedTy =
+ S.Context.getTypedefType(ElaboratedTypeKeyword::None,
+ /*Qualifier=*/std::nullopt, TD);
}
}
}
@@ -9617,7 +9627,10 @@ struct SearchNonTrivialToInitializeField
S.DiagRuntimeBehavior(SL, E, S.PDiag(diag::note_nontrivial_field) << 1);
}
void visitStruct(QualType FT, SourceLocation SL) {
- for (const FieldDecl *FD : FT->castAs<RecordType>()->getDecl()->fields())
+ for (const FieldDecl *FD : FT->castAs<RecordType>()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->fields())
visit(FD->getType(), FD->getLocation());
}
void visitArray(QualType::PrimitiveDefaultInitializeKind PDIK,
@@ -9662,7 +9675,10 @@ struct SearchNonTrivialToCopyField
S.DiagRuntimeBehavior(SL, E, S.PDiag(diag::note_nontrivial_field) << 0);
}
void visitStruct(QualType FT, SourceLocation SL) {
- for (const FieldDecl *FD : FT->castAs<RecordType>()->getDecl()->fields())
+ for (const FieldDecl *FD : FT->castAs<RecordType>()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->fields())
visit(FD->getType(), FD->getLocation());
}
void visitArray(QualType::PrimitiveCopyKind PCK, const ArrayType *AT,
@@ -9943,8 +9959,9 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call,
getLangOpts().CPlusPlus && !RT->isIncompleteType() &&
!RT->desugar().isTriviallyCopyableType(Context);
+ const auto *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
if ((BId == Builtin::BImemset || BId == Builtin::BIbzero) &&
- RT->getDecl()->isNonTrivialToPrimitiveDefaultInitialize()) {
+ RD->isNonTrivialToPrimitiveDefaultInitialize()) {
DiagRuntimeBehavior(Dest->getExprLoc(), Dest,
PDiag(diag::warn_cstruct_memaccess)
<< ArgIdx << FnName << PointeeTy << 0);
@@ -9957,7 +9974,7 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call,
PDiag(diag::warn_cxxstruct_memaccess)
<< FnName << PointeeTy);
} else if ((BId == Builtin::BImemcpy || BId == Builtin::BImemmove) &&
- RT->getDecl()->isNonTrivialToPrimitiveCopy()) {
+ RD->isNonTrivialToPrimitiveCopy()) {
DiagRuntimeBehavior(Dest->getExprLoc(), Dest,
PDiag(diag::warn_cstruct_memaccess)
<< ArgIdx << FnName << PointeeTy << 1);
@@ -10463,10 +10480,14 @@ struct IntRange {
if (!C.getLangOpts().CPlusPlus) {
// For enum types in C code, use the underlying datatype.
if (const auto *ET = dyn_cast<EnumType>(T))
- T = ET->getDecl()->getIntegerType().getDesugaredType(C).getTypePtr();
+ T = ET->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->getIntegerType()
+ .getDesugaredType(C)
+ .getTypePtr();
} else if (const auto *ET = dyn_cast<EnumType>(T)) {
// For enum types in C++, use the known bit width of the enumerators.
- EnumDecl *Enum = ET->getDecl();
+ EnumDecl *Enum = ET->getOriginalDecl()->getDefinitionOrSelf();
// In C++11, enums can have a fixed underlying type. Use this type to
// compute the range.
if (Enum->isFixed()) {
@@ -10508,7 +10529,9 @@ struct IntRange {
if (const AtomicType *AT = dyn_cast<AtomicType>(T))
T = AT->getValueType().getTypePtr();
if (const EnumType *ET = dyn_cast<EnumType>(T))
- T = C.getCanonicalType(ET->getDecl()->getIntegerType()).getTypePtr();
+ T = C.getCanonicalType(
+ ET->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType())
+ .getTypePtr();
if (const auto *EIT = dyn_cast<BitIntType>(T))
return IntRange(EIT->getNumBits(), EIT->isUnsigned());
@@ -11480,7 +11503,9 @@ static bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init,
return false;
if (BitfieldType->isEnumeralType()) {
- EnumDecl *BitfieldEnumDecl = BitfieldType->castAs<EnumType>()->getDecl();
+ EnumDecl *BitfieldEnumDecl = BitfieldType->castAs<EnumType>()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf();
// If the underlying enum type was not explicitly specified as an unsigned
// type and the enum contain only positive values, MSVC++ will cause an
// inconsistency by storing this as a signed type.
@@ -11517,7 +11542,7 @@ static bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init,
EnumTy = PTAttr->getType()->getAs<EnumType>();
}
if (EnumTy) {
- EnumDecl *ED = EnumTy->getDecl();
+ EnumDecl *ED = EnumTy->getOriginalDecl()->getDefinitionOrSelf();
bool SignedBitfield = BitfieldType->isSignedIntegerOrEnumerationType();
// Enum types are implicitly signed on Windows, so check if there are any
@@ -12583,8 +12608,8 @@ void Sema::CheckImplicitConversion(Expr *E, QualType T, SourceLocation CC,
if (const EnumType *SourceEnum = Source->getAs<EnumType>())
if (const EnumType *TargetEnum = Target->getAs<EnumType>())
- if (SourceEnum->getDecl()->hasNameForLinkage() &&
- TargetEnum->getDecl()->hasNameForLinkage() &&
+ if (SourceEnum->getOriginalDecl()->hasNameForLinkage() &&
+ TargetEnum->getOriginalDecl()->hasNameForLinkage() &&
SourceEnum != TargetEnum) {
if (SourceMgr.isInSystemMacro(CC))
return;
@@ -15108,10 +15133,9 @@ static bool isLayoutCompatible(const ASTContext &C, const EnumDecl *ED1,
static bool isLayoutCompatible(const ASTContext &C, const FieldDecl *Field1,
const FieldDecl *Field2,
bool AreUnionMembers = false) {
- [[maybe_unused]] const Type *Field1Parent =
- Field1->getParent()->getTypeForDecl();
- [[maybe_unused]] const Type *Field2Parent =
- Field2->getParent()->getTypeForDecl();
+#ifndef NDEBUG
+ CanQualType Field1Parent = C.getCanonicalTagType(Field1->getParent());
+ CanQualType Field2Parent = C.getCanonicalTagType(Field2->getParent());
assert(((Field1Parent->isStructureOrClassType() &&
Field2Parent->isStructureOrClassType()) ||
(Field1Parent->isUnionType() && Field2Parent->isUnionType())) &&
@@ -15120,6 +15144,7 @@ static bool isLayoutCompatible(const ASTContext &C, const FieldDecl *Field1,
assert(((!AreUnionMembers && Field1Parent->isStructureOrClassType()) ||
(AreUnionMembers && Field1Parent->isUnionType())) &&
"AreUnionMembers should be 'true' for union fields (only).");
+#endif
if (!isLayoutCompatible(C, Field1->getType(), Field2->getType()))
return false;
@@ -15224,16 +15249,16 @@ static bool isLayoutCompatible(const ASTContext &C, QualType T1, QualType T2) {
return false;
if (TC1 == Type::Enum) {
- return isLayoutCompatible(C,
- cast<EnumType>(T1)->getDecl(),
- cast<EnumType>(T2)->getDecl());
+ return isLayoutCompatible(
+ C, cast<EnumType>(T1)->getOriginalDecl()->getDefinitionOrSelf(),
+ cast<EnumType>(T2)->getOriginalDecl()->getDefinitionOrSelf());
} else if (TC1 == Type::Record) {
if (!T1->isStandardLayoutType() || !T2->isStandardLayoutType())
return false;
- return isLayoutCompatible(C,
- cast<RecordType>(T1)->getDecl(),
- cast<RecordType>(T2)->getDecl());
+ return isLayoutCompatible(
+ C, cast<RecordType>(T1)->getOriginalDecl()->getDefinitionOrSelf(),
+ cast<RecordType>(T2)->getOriginalDecl()->getDefinitionOrSelf());
}
return false;
@@ -15587,7 +15612,9 @@ void Sema::RefersToMemberWithReducedAlignment(
return;
if (ME->isArrow())
BaseType = BaseType->getPointeeType();
- RecordDecl *RD = BaseType->castAs<RecordType>()->getDecl();
+ RecordDecl *RD = BaseType->castAs<RecordType>()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf();
if (RD->isInvalidDecl())
return;
@@ -15632,7 +15659,7 @@ void Sema::RefersToMemberWithReducedAlignment(
// Compute the CompleteObjectAlignment as the alignment of the whole chain.
CharUnits CompleteObjectAlignment = Context.getTypeAlignInChars(
- ReverseMemberChain.back()->getParent()->getTypeForDecl());
+ Context.getCanonicalTagType(ReverseMemberChain.back()->getParent()));
// The base expression of the innermost MemberExpr may give
// stronger guarantees than the class containing the member.
@@ -15662,9 +15689,9 @@ void Sema::RefersToMemberWithReducedAlignment(
if (FDI->hasAttr<PackedAttr>() ||
FDI->getParent()->hasAttr<PackedAttr>()) {
FD = FDI;
- Alignment = std::min(
- Context.getTypeAlignInChars(FD->getType()),
- Context.getTypeAlignInChars(FD->getParent()->getTypeForDecl()));
+ Alignment = std::min(Context.getTypeAlignInChars(FD->getType()),
+ Context.getTypeAlignInChars(
+ Context.getCanonicalTagType(FD->getParent())));
break;
}
}
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index a43ac9eb7610d..99492cea4e6c2 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -732,7 +732,7 @@ ResultBuilder::ShadowMapEntry::end() const {
///
/// \returns a nested name specifier that refers into the target context, or
/// NULL if no qualification is needed.
-static NestedNameSpecifier *
+static NestedNameSpecifier
getRequiredQualification(ASTContext &Context, const DeclContext *CurContext,
const DeclContext *TargetContext) {
SmallVector<const DeclContext *, 4> TargetParents;
@@ -747,7 +747,7 @@ getRequiredQualification(ASTContext &Context, const DeclContext *CurContext,
TargetParents.push_back(CommonAncestor);
}
- NestedNameSpecifier *Result = nullptr;
+ NestedNameSpecifier Result = std::nullopt;
while (!TargetParents.empty()) {
const DeclContext *Parent = TargetParents.pop_back_val();
@@ -755,10 +755,12 @@ getRequiredQualification(ASTContext &Context, const DeclContext *CurContext,
if (!Namespace->getIdentifier())
continue;
- Result = NestedNameSpecifier::Create(Context, Result, Namespace);
- } else if (const auto *TD = dyn_cast<TagDecl>(Parent))
- Result = NestedNameSpecifier::Create(
- Context, Result, Context.getTypeDeclType(TD).getTypePtr());
+ Result = NestedNameSpecifier(Context, Namespace, Result);
+ } else if (const auto *TD = dyn_cast<TagDecl>(Parent)) {
+ QualType TT = Context.getTagType(ElaboratedTypeKeyword::None, Result, TD,
+ /*OwnsTag=*/false);
+ Result = NestedNameSpecifier(TT.getTypePtr());
+ }
}
return Result;
}
@@ -937,11 +939,12 @@ SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
/// Get the type that a given expression will have if this declaration
/// is used as an expression in its "typical" code-completion form.
-QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) {
+QualType clang::getDeclUsageType(ASTContext &C, NestedNameSpecifier Qualifier,
+ const NamedDecl *ND) {
ND = ND->getUnderlyingDecl();
if (const auto *Type = dyn_cast<TypeDecl>(ND))
- return C.getTypeDeclType(Type);
+ return C.getTypeDeclType(ElaboratedTypeKeyword::None, Qualifier, Type);
if (const auto *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
return C.getObjCInterfaceType(Iface);
@@ -951,7 +954,9 @@ QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) {
else if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND))
T = Method->getSendResultType();
else if (const auto *Enumerator = dyn_cast<EnumConstantDecl>(ND))
- T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
+ T = C.getTagType(ElaboratedTypeKeyword::None, Qualifier,
+ cast<EnumDecl>(Enumerator->getDeclContext()),
+ /*OwnsTag=*/false);
else if (const auto *Property = dyn_cast<ObjCPropertyDecl>(ND))
T = Property->getType();
else if (const auto *Value = dyn_cast<ValueDecl>(ND))
@@ -1053,7 +1058,7 @@ void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
// If we have a preferred type, adjust the priority for results with exactly-
// matching or nearly-matching types.
if (!PreferredType.isNull()) {
- QualType T = getDeclUsageType(SemaRef.Context, R.Declaration);
+ QualType T = getDeclUsageType(SemaRef.Context, R.Qualifier, R.Declaration);
if (!T.isNull()) {
CanQualType TC = SemaRef.Context.getCanonicalType(T);
// Check for exactly-matching types (modulo qualifiers).
@@ -1070,10 +1075,9 @@ void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
static DeclContext::lookup_result getConstructors(ASTContext &Context,
const CXXRecordDecl *Record) {
- QualType RecordTy = Context.getTypeDeclType(Record);
+ CanQualType RecordTy = Context.getCanonicalTagType(Record);
DeclarationName ConstructorName =
- Context.DeclarationNames.getCXXConstructorName(
- Context.getCanonicalType(RecordTy));
+ Context.DeclarationNames.getCXXConstructorName(RecordTy);
return Record->lookup(ConstructorName);
}
@@ -1216,11 +1220,13 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
const DeclContext *Ctx = R.Declaration->getDeclContext();
if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
R.Qualifier =
- NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace);
+ NestedNameSpecifier(SemaRef.Context, Namespace, std::nullopt);
else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
- R.Qualifier = NestedNameSpecifier::Create(
- SemaRef.Context, nullptr,
- SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
+ R.Qualifier = NestedNameSpecifier(
+ SemaRef.Context
+ .getTagType(ElaboratedTypeKeyword::None,
+ /*Qualifier=*/std::nullopt, Tag, /*OwnsTag=*/false)
+ .getTypePtr());
else
R.QualifierIsInformative = false;
}
@@ -1405,11 +1411,13 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
const DeclContext *Ctx = R.Declaration->getDeclContext();
if (const auto *Namespace = dyn_cast<NamespaceDecl>(Ctx))
R.Qualifier =
- NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace);
+ NestedNameSpecifier(SemaRef.Context, Namespace, std::nullopt);
else if (const auto *Tag = dyn_cast<TagDecl>(Ctx))
- R.Qualifier = NestedNameSpecifier::Create(
- SemaRef.Context, nullptr,
- SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
+ R.Qualifier = NestedNameSpecifier(
+ SemaRef.Context
+ .getTagType(ElaboratedTypeKeyword::None,
+ /*Qualifier=*/std::nullopt, Tag, /*OwnsTag=*/false)
+ .getTypePtr());
else
R.QualifierIsInformative = false;
}
@@ -1664,7 +1672,8 @@ static bool isObjCReceiverType(ASTContext &C, QualType T) {
}
bool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const {
- QualType T = getDeclUsageType(SemaRef.Context, ND);
+ QualType T =
+ getDeclUsageType(SemaRef.Context, /*Qualifier=*/std::nullopt, ND);
if (T.isNull())
return false;
@@ -1689,7 +1698,8 @@ bool ResultBuilder::IsObjCCollection(const NamedDecl *ND) const {
(!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
return false;
- QualType T = getDeclUsageType(SemaRef.Context, ND);
+ QualType T =
+ getDeclUsageType(SemaRef.Context, /*Qualifier=*/std::nullopt, ND);
if (T.isNull())
return false;
@@ -1745,8 +1755,10 @@ class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
bool InBaseClass) override {
- ResultBuilder::Result Result(ND, Results.getBasePriority(ND), nullptr,
- false, IsAccessible(ND, Ctx), FixIts);
+ ResultBuilder::Result Result(ND, Results.getBasePriority(ND),
+ /*Qualifier=*/std::nullopt,
+ /*QualifierIsInformative=*/false,
+ IsAccessible(ND, Ctx), FixIts);
Results.AddResult(Result, InitialLookupCtx, Hiding, InBaseClass, BaseType);
}
@@ -2010,7 +2022,6 @@ static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
Policy.AnonymousTagLocations = false;
Policy.SuppressStrongLifetime = true;
Policy.SuppressUnwrittenScope = true;
- Policy.SuppressScope = true;
Policy.CleanUglifiedParameters = true;
return Policy;
}
@@ -2035,7 +2046,7 @@ static const char *GetCompletionTypeString(QualType T, ASTContext &Context,
// Anonymous tag types are constant strings.
if (const TagType *TagT = dyn_cast<TagType>(T))
- if (TagDecl *Tag = TagT->getDecl())
+ if (TagDecl *Tag = TagT->getOriginalDecl())
if (!Tag->hasNameForLinkage()) {
switch (Tag->getTagKind()) {
case TagTypeKind::Struct:
@@ -2925,8 +2936,8 @@ static void AddResultTypeChunk(ASTContext &Context,
else
T = Method->getReturnType();
} else if (const auto *Enumerator = dyn_cast<EnumConstantDecl>(ND)) {
- T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
- T = clang::TypeName::getFullyQualifiedType(T, Context);
+ T = Context.getCanonicalTagType(
+ cast<EnumDecl>(Enumerator->getDeclContext()));
} else if (isa<UnresolvedUsingValueDecl>(ND)) {
/* Do nothing: ignore unresolved using declarations*/
} else if (const auto *Ivar = dyn_cast<ObjCIvarDecl>(ND)) {
@@ -3021,7 +3032,7 @@ static void findTypeLocationForBlockDecl(const TypeSourceInfo *TSInfo,
if (!SuppressBlock) {
if (TypedefTypeLoc TypedefTL = TL.getAsAdjusted<TypedefTypeLoc>()) {
if (TypeSourceInfo *InnerTSInfo =
- TypedefTL.getTypedefNameDecl()->getTypeSourceInfo()) {
+ TypedefTL.getDecl()->getTypeSourceInfo()) {
TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
continue;
}
@@ -3381,7 +3392,7 @@ static void AddTemplateParameterChunks(
/// Add a qualifier to the given code-completion string, if the
/// provided nested-name-specifier is non-NULL.
static void AddQualifierToCompletionString(CodeCompletionBuilder &Result,
- NestedNameSpecifier *Qualifier,
+ NestedNameSpecifier Qualifier,
bool QualifierIsInformative,
ASTContext &Context,
const PrintingPolicy &Policy) {
@@ -3391,7 +3402,7 @@ static void AddQualifierToCompletionString(CodeCompletionBuilder &Result,
std::string PrintedNNS;
{
llvm::raw_string_ostream OS(PrintedNNS);
- Qualifier->print(OS, Policy);
+ Qualifier.print(OS, Policy);
}
if (QualifierIsInformative)
Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
@@ -3520,11 +3531,9 @@ static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
case DeclarationName::CXXConstructorName: {
CXXRecordDecl *Record = nullptr;
QualType Ty = Name.getCXXNameType();
- if (const auto *RecordTy = Ty->getAs<RecordType>())
- Record = cast<CXXRecordDecl>(RecordTy->getDecl());
- else if (const auto *InjectedTy = Ty->getAs<InjectedClassNameType>())
- Record = InjectedTy->getDecl();
- else {
+ if (auto *RD = Ty->getAsCXXRecordDecl()) {
+ Record = RD;
+ } else {
Result.AddTypedTextChunk(
Result.getAllocator().CopyString(ND->getNameAsString()));
break;
@@ -4498,12 +4507,12 @@ static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
// If we need a nested-name-specifier, add one now.
if (!InContext) {
- NestedNameSpecifier *NNS = getRequiredQualification(
+ NestedNameSpecifier NNS = getRequiredQualification(
S.Context, CurContext, Overridden->getDeclContext());
if (NNS) {
std::string Str;
llvm::raw_string_ostream OS(Str);
- NNS->print(OS, Policy);
+ NNS.print(OS, Policy);
Builder.AddTextChunk(Results.getAllocator().CopyString(Str));
}
} else if (!InContext->Equals(Overridden->getDeclContext()))
@@ -4912,14 +4921,14 @@ namespace {
/// Information that allows to avoid completing redundant enumerators.
struct CoveredEnumerators {
llvm::SmallPtrSet<EnumConstantDecl *, 8> Seen;
- NestedNameSpecifier *SuggestedQualifier = nullptr;
+ NestedNameSpecifier SuggestedQualifier = std::nullopt;
};
} // namespace
static void AddEnumerators(ResultBuilder &Results, ASTContext &Context,
EnumDecl *Enum, DeclContext *CurContext,
const CoveredEnumerators &Enumerators) {
- NestedNameSpecifier *Qualifier = Enumerators.SuggestedQualifier;
+ NestedNameSpecifier Qualifier = Enumerators.SuggestedQualifier;
if (Context.getLangOpts().CPlusPlus && !Qualifier && Enumerators.Seen.empty()) {
// If there are no prior enumerators in C++, check whether we have to
// qualify the names of the enumerators that we suggest, because they
@@ -5051,9 +5060,9 @@ void SemaCodeCompletion::CodeCompleteExpression(
Data.PreferredType->isMemberPointerType() ||
Data.PreferredType->isBlockPointerType();
if (Data.PreferredType->isEnumeralType()) {
- EnumDecl *Enum = Data.PreferredType->castAs<EnumType>()->getDecl();
- if (auto *Def = Enum->getDefinition())
- Enum = Def;
+ EnumDecl *Enum = Data.PreferredType->castAs<EnumType>()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf();
// FIXME: collect covered enumerators in cases like:
// if (x == my_enum::one) { ... } else if (x == ^) {}
AddEnumerators(Results, getASTContext(), Enum, SemaRef.CurContext,
@@ -5177,7 +5186,8 @@ AddObjCProperties(const CodeCompletionContext &CCContext,
// expressions.
if (!P->getType().getTypePtr()->isBlockPointerType() ||
!IsBaseExprStatement) {
- Result R = Result(P, Results.getBasePriority(P), nullptr);
+ Result R =
+ Result(P, Results.getBasePriority(P), /*Qualifier=*/std::nullopt);
if (!InOriginalClass)
setInBaseClass(R);
Results.MaybeAddResult(R, CurContext);
@@ -5191,7 +5201,8 @@ AddObjCProperties(const CodeCompletionContext &CCContext,
findTypeLocationForBlockDecl(P->getTypeSourceInfo(), BlockLoc,
BlockProtoLoc);
if (!BlockLoc) {
- Result R = Result(P, Results.getBasePriority(P), nullptr);
+ Result R =
+ Result(P, Results.getBasePriority(P), /*Qualifier=*/std::nullopt);
if (!InOriginalClass)
setInBaseClass(R);
Results.MaybeAddResult(R, CurContext);
@@ -5603,15 +5614,18 @@ class ConceptInfo {
// In T::foo, `foo` is a static member function/variable.
bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) override {
- if (E->getQualifier() && isApprox(E->getQualifier()->getAsType(), T))
+ NestedNameSpecifier Qualifier = E->getQualifier();
+ if (Qualifier.getKind() == NestedNameSpecifier::Kind::Type &&
+ isApprox(Qualifier.getAsType(), T))
addValue(E, E->getDeclName(), Member::Colons);
return true;
}
// In T::typename foo, `foo` is a type.
bool VisitDependentNameType(DependentNameType *DNT) override {
- const auto *Q = DNT->getQualifier();
- if (Q && isApprox(Q->getAsType(), T))
+ NestedNameSpecifier Q = DNT->getQualifier();
+ if (Q.getKind() == NestedNameSpecifier::Kind::Type &&
+ isApprox(Q.getAsType(), T))
addType(DNT->getIdentifier());
return true;
}
@@ -5620,10 +5634,15 @@ class ConceptInfo {
// VisitNNS() doesn't exist, and TraverseNNS isn't always called :-(
bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSL) override {
if (NNSL) {
- NestedNameSpecifier *NNS = NNSL.getNestedNameSpecifier();
- const auto *Q = NNS->getPrefix();
- if (Q && isApprox(Q->getAsType(), T))
- addType(NNS->getAsIdentifier());
+ NestedNameSpecifier NNS = NNSL.getNestedNameSpecifier();
+ if (NNS.getKind() == NestedNameSpecifier::Kind::Type) {
+ const Type *NNST = NNS.getAsType();
+ if (NestedNameSpecifier Q = NNST->getPrefix();
+ Q.getKind() == NestedNameSpecifier::Kind::Type &&
+ isApprox(Q.getAsType(), T))
+ if (const auto *DNT = dyn_cast_or_null<DependentNameType>(NNST))
+ addType(DNT->getIdentifier());
+ }
}
// FIXME: also handle T::foo<X>::bar
return DynamicRecursiveASTVisitor::TraverseNestedNameSpecifierLoc(NNSL);
@@ -5769,7 +5788,7 @@ QualType getApproximateType(const Expr *E, HeuristicResolver &Resolver) {
if (auto Decls = Resolver.resolveDependentNameType(DNT);
Decls.size() == 1) {
if (const auto *TD = dyn_cast<TypeDecl>(Decls[0]))
- return QualType(TD->getTypeForDecl(), 0);
+ return TD->getASTContext().getTypeDeclType(TD);
}
}
// We only resolve DependentTy, or undeduced autos (including auto* etc).
@@ -6176,9 +6195,8 @@ void SemaCodeCompletion::CodeCompleteCase(Scope *S) {
// Code-complete the cases of a switch statement over an enumeration type
// by providing the list of
- EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
- if (EnumDecl *Def = Enum->getDefinition())
- Enum = Def;
+ EnumDecl *Enum =
+ type->castAs<EnumType>()->getOriginalDecl()->getDefinitionOrSelf();
// Determine which enumerators we have already seen in the switch statement.
// FIXME: Ideally, we would also be able to look *past* the code-completion
@@ -6879,8 +6897,8 @@ void SemaCodeCompletion::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
// Try to instantiate any non-dependent declaration contexts before
// we look in them. Bail out if we fail.
- NestedNameSpecifier *NNS = SS.getScopeRep();
- if (NNS != nullptr && SS.isValid() && !NNS->isDependent()) {
+ NestedNameSpecifier NNS = SS.getScopeRep();
+ if (NNS && !NNS.isDependent()) {
if (Ctx == nullptr || SemaRef.RequireCompleteDeclContext(SS, Ctx))
return;
}
@@ -6894,14 +6912,13 @@ void SemaCodeCompletion::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
// The "template" keyword can follow "::" in the grammar, but only
// put it into the grammar if the nested-name-specifier is dependent.
// FIXME: results is always empty, this appears to be dead.
- if (!Results.empty() && NNS && NNS->isDependent())
+ if (!Results.empty() && NNS.isDependent())
Results.AddResult("template");
// If the scope is a concept-constrained type parameter, infer nested
// members based on the constraints.
- if (NNS) {
- if (const auto *TTPT =
- dyn_cast_or_null<TemplateTypeParmType>(NNS->getAsType())) {
+ if (NNS.getKind() == NestedNameSpecifier::Kind::Type) {
+ if (const auto *TTPT = dyn_cast<TemplateTypeParmType>(NNS.getAsType())) {
for (const auto &R : ConceptInfo(*TTPT, S).members()) {
if (R.Operator != ConceptInfo::Member::Colons)
continue;
@@ -7026,7 +7043,7 @@ void SemaCodeCompletion::CodeCompleteNamespaceDecl(Scope *S) {
NS != NSEnd; ++NS)
Results.AddResult(
CodeCompletionResult(NS->second, Results.getBasePriority(NS->second),
- nullptr),
+ /*Qualifier=*/std::nullopt),
SemaRef.CurContext, nullptr, false);
Results.ExitScope();
}
@@ -7813,7 +7830,8 @@ static void AddObjCMethods(ObjCContainerDecl *Container,
if (!Selectors.insert(M->getSelector()).second)
continue;
- Result R = Result(M, Results.getBasePriority(M), nullptr);
+ Result R =
+ Result(M, Results.getBasePriority(M), /*Qualifier=*/std::nullopt);
R.StartParameter = SelIdents.size();
R.AllParametersAreInformative = (WantKind != MK_Any);
if (!InOriginalClass)
@@ -8404,7 +8422,8 @@ AddClassMessageCompletions(Sema &SemaRef, Scope *S, ParsedType Receiver,
continue;
Result R(MethList->getMethod(),
- Results.getBasePriority(MethList->getMethod()), nullptr);
+ Results.getBasePriority(MethList->getMethod()),
+ /*Qualifier=*/std::nullopt);
R.StartParameter = SelIdents.size();
R.AllParametersAreInformative = false;
Results.MaybeAddResult(R, SemaRef.CurContext);
@@ -8580,7 +8599,8 @@ void SemaCodeCompletion::CodeCompleteObjCInstanceMessage(
continue;
Result R(MethList->getMethod(),
- Results.getBasePriority(MethList->getMethod()), nullptr);
+ Results.getBasePriority(MethList->getMethod()),
+ /*Qualifier=*/std::nullopt);
R.StartParameter = SelIdents.size();
R.AllParametersAreInformative = false;
Results.MaybeAddResult(R, SemaRef.CurContext);
@@ -8696,9 +8716,9 @@ static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
// Record any protocols we find.
if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(D))
if (!OnlyForwardDeclarations || !Proto->hasDefinition())
- Results.AddResult(
- Result(Proto, Results.getBasePriority(Proto), nullptr), CurContext,
- nullptr, false);
+ Results.AddResult(Result(Proto, Results.getBasePriority(Proto),
+ /*Qualifier=*/std::nullopt),
+ CurContext, nullptr, false);
}
}
@@ -8764,9 +8784,9 @@ static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
if (const auto *Class = dyn_cast<ObjCInterfaceDecl>(D))
if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
(!OnlyUnimplemented || !Class->getImplementation()))
- Results.AddResult(
- Result(Class, Results.getBasePriority(Class), nullptr), CurContext,
- nullptr, false);
+ Results.AddResult(Result(Class, Results.getBasePriority(Class),
+ /*Qualifier=*/std::nullopt),
+ CurContext, nullptr, false);
}
}
@@ -8878,9 +8898,9 @@ void SemaCodeCompletion::CodeCompleteObjCInterfaceCategory(
for (const auto *D : TU->decls())
if (const auto *Category = dyn_cast<ObjCCategoryDecl>(D))
if (CategoryNames.insert(Category->getIdentifier()).second)
- Results.AddResult(
- Result(Category, Results.getBasePriority(Category), nullptr),
- SemaRef.CurContext, nullptr, false);
+ Results.AddResult(Result(Category, Results.getBasePriority(Category),
+ /*Qualifier=*/std::nullopt),
+ SemaRef.CurContext, nullptr, false);
Results.ExitScope();
HandleCodeCompleteResults(&SemaRef, CodeCompleter,
@@ -8915,7 +8935,8 @@ void SemaCodeCompletion::CodeCompleteObjCImplementationCategory(
for (const auto *Cat : Class->visible_categories()) {
if ((!IgnoreImplemented || !Cat->getImplementation()) &&
CategoryNames.insert(Cat->getIdentifier()).second)
- Results.AddResult(Result(Cat, Results.getBasePriority(Cat), nullptr),
+ Results.AddResult(Result(Cat, Results.getBasePriority(Cat),
+ /*Qualifier=*/std::nullopt),
SemaRef.CurContext, nullptr, false);
}
@@ -9015,7 +9036,8 @@ void SemaCodeCompletion::CodeCompleteObjCPropertySynthesizeIvar(
for (; Class; Class = Class->getSuperClass()) {
for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
Ivar = Ivar->getNextIvar()) {
- Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), nullptr),
+ Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar),
+ /*Qualifier=*/std::nullopt),
SemaRef.CurContext, nullptr, false);
// Determine whether we've seen an ivar with a name similar to the
@@ -10031,7 +10053,8 @@ void SemaCodeCompletion::CodeCompleteObjCMethodDeclSelector(
}
Result R(MethList->getMethod(),
- Results.getBasePriority(MethList->getMethod()), nullptr);
+ Results.getBasePriority(MethList->getMethod()),
+ /*Qualifier=*/std::nullopt);
R.StartParameter = SelIdents.size();
R.AllParametersAreInformative = false;
R.DeclaringEntity = true;
diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp
index a1389c6c034b1..b6843a8795459 100644
--- a/clang/lib/Sema/SemaCoroutine.cpp
+++ b/clang/lib/Sema/SemaCoroutine.cpp
@@ -89,8 +89,8 @@ static QualType lookupPromiseType(Sema &S, const FunctionDecl *FD,
AddArg(T);
// Build the template-id.
- QualType CoroTrait =
- S.CheckTemplateIdType(TemplateName(CoroTraits), KwLoc, Args);
+ QualType CoroTrait = S.CheckTemplateIdType(
+ ElaboratedTypeKeyword::None, TemplateName(CoroTraits), KwLoc, Args);
if (CoroTrait.isNull())
return QualType();
if (S.RequireCompleteType(KwLoc, CoroTrait,
@@ -111,23 +111,18 @@ static QualType lookupPromiseType(Sema &S, const FunctionDecl *FD,
<< RD;
return QualType();
}
- // The promise type is required to be a class type.
- QualType PromiseType = S.Context.getTypeDeclType(Promise);
-
- auto buildElaboratedType = [&]() {
- auto *NNS = NestedNameSpecifier::Create(S.Context, nullptr, S.getStdNamespace());
- NNS = NestedNameSpecifier::Create(S.Context, NNS, CoroTrait.getTypePtr());
- return S.Context.getElaboratedType(ElaboratedTypeKeyword::None, NNS,
- PromiseType);
- };
+ NestedNameSpecifier Qualifier(CoroTrait.getTypePtr());
+ QualType PromiseType = S.Context.getTypeDeclType(ElaboratedTypeKeyword::None,
+ Qualifier, Promise);
+ // The promise type is required to be a class type.
if (!PromiseType->getAsCXXRecordDecl()) {
S.Diag(FuncLoc,
diag::err_implied_std_coroutine_traits_promise_type_not_class)
- << buildElaboratedType();
+ << PromiseType;
return QualType();
}
- if (S.RequireCompleteType(FuncLoc, buildElaboratedType(),
+ if (S.RequireCompleteType(FuncLoc, PromiseType,
diag::err_coroutine_promise_type_incomplete))
return QualType();
@@ -167,8 +162,8 @@ static QualType lookupCoroutineHandleType(Sema &S, QualType PromiseType,
S.Context.getTrivialTypeSourceInfo(PromiseType, Loc)));
// Build the template-id.
- QualType CoroHandleType =
- S.CheckTemplateIdType(TemplateName(CoroHandle), Loc, Args);
+ QualType CoroHandleType = S.CheckTemplateIdType(
+ ElaboratedTypeKeyword::None, TemplateName(CoroHandle), Loc, Args);
if (CoroHandleType.isNull())
return QualType();
if (S.RequireCompleteType(Loc, CoroHandleType,
@@ -643,7 +638,9 @@ static void checkNoThrow(Sema &S, const Stmt *E,
QualType::DestructionKind::DK_cxx_destructor) {
const auto *T =
cast<RecordType>(ReturnType.getCanonicalType().getTypePtr());
- checkDeclNoexcept(cast<CXXRecordDecl>(T->getDecl())->getDestructor(),
+ checkDeclNoexcept(cast<CXXRecordDecl>(T->getOriginalDecl())
+ ->getDefinition()
+ ->getDestructor(),
/*IsDtor=*/true);
}
} else
@@ -1082,9 +1079,9 @@ static Expr *buildStdNoThrowDeclRef(Sema &S, SourceLocation Loc) {
static TypeSourceInfo *getTypeSourceInfoForStdAlignValT(Sema &S,
SourceLocation Loc) {
- EnumDecl *StdAlignValT = S.getStdAlignValT();
- QualType StdAlignValDecl = S.Context.getTypeDeclType(StdAlignValT);
- return S.Context.getTrivialTypeSourceInfo(StdAlignValDecl);
+ EnumDecl *StdAlignValDecl = S.getStdAlignValT();
+ CanQualType StdAlignValT = S.Context.getCanonicalTagType(StdAlignValDecl);
+ return S.Context.getTrivialTypeSourceInfo(StdAlignValT);
}
// When searching for custom allocators on the PromiseType we want to
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 11cbda412667f..ef74dddc218bb 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -140,8 +140,8 @@ class TypeNameValidatorCCC final : public CorrectionCandidateCallback {
} // end anonymous namespace
-QualType Sema::getTypeDeclType(DeclContext *LookupCtx, DiagCtorKind DCK,
- TypeDecl *TD, SourceLocation NameLoc) {
+void Sema::checkTypeDeclType(DeclContext *LookupCtx, DiagCtorKind DCK,
+ TypeDecl *TD, SourceLocation NameLoc) {
auto *LookupRD = dyn_cast_or_null<CXXRecordDecl>(LookupCtx);
auto *FoundRD = dyn_cast<CXXRecordDecl>(TD);
if (DCK != DiagCtorKind::None && LookupRD && FoundRD &&
@@ -157,7 +157,6 @@ QualType Sema::getTypeDeclType(DeclContext *LookupCtx, DiagCtorKind DCK,
DiagnoseUseOfDecl(TD, NameLoc);
MarkAnyDeclReferenced(TD->getLocation(), TD, /*OdrUse=*/false);
- return Context.getTypeDeclType(TD);
}
namespace {
@@ -182,13 +181,13 @@ lookupUnqualifiedTypeNameInBase(Sema &S, const IdentifierInfo &II,
UnqualifiedTypeNameLookupResult FoundTypeDecl =
UnqualifiedTypeNameLookupResult::NotFound;
for (const auto &Base : RD->bases()) {
- const CXXRecordDecl *BaseRD = nullptr;
- if (auto *BaseTT = Base.getType()->getAs<TagType>())
- BaseRD = BaseTT->getAsCXXRecordDecl();
- else if (auto *TST = Base.getType()->getAs<TemplateSpecializationType>()) {
+ const CXXRecordDecl *BaseRD = Base.getType()->getAsCXXRecordDecl();
+ if (BaseRD) {
+ } else if (auto *TST = dyn_cast<TemplateSpecializationType>(
+ Base.getType().getCanonicalType())) {
// Look for type decls in dependent base classes that have known primary
// templates.
- if (!TST || !TST->isDependentType())
+ if (!TST->isDependentType())
continue;
auto *TD = TST->getTemplateName().getAsTemplateDecl();
if (!TD)
@@ -253,8 +252,7 @@ static ParsedType recoverFromTypeInKnownDependentBase(Sema &S,
S.Diag(NameLoc, diag::ext_found_in_dependent_base) << &II;
ASTContext &Context = S.Context;
- auto *NNS = NestedNameSpecifier::Create(
- Context, nullptr, cast<Type>(Context.getRecordType(RD)));
+ NestedNameSpecifier NNS(Context.getCanonicalTagType(RD).getTypePtr());
QualType T =
Context.getDependentNameType(ElaboratedTypeKeyword::None, NNS, &II);
@@ -269,45 +267,6 @@ static ParsedType recoverFromTypeInKnownDependentBase(Sema &S,
return S.CreateParsedType(T, Builder.getTypeSourceInfo(Context, T));
}
-/// Build a ParsedType for a simple-type-specifier with a nested-name-specifier.
-static ParsedType buildNamedType(Sema &S, const CXXScopeSpec *SS, QualType T,
- SourceLocation NameLoc,
- bool WantNontrivialTypeSourceInfo = true) {
- switch (T->getTypeClass()) {
- case Type::DeducedTemplateSpecialization:
- case Type::Enum:
- case Type::InjectedClassName:
- case Type::Record:
- case Type::Typedef:
- case Type::UnresolvedUsing:
- case Type::Using:
- break;
- // These can never be qualified so an ElaboratedType node
- // would carry no additional meaning.
- case Type::ObjCInterface:
- case Type::ObjCTypeParam:
- case Type::TemplateTypeParm:
- return ParsedType::make(T);
- default:
- llvm_unreachable("Unexpected Type Class");
- }
-
- if (!SS || SS->isEmpty())
- return ParsedType::make(S.Context.getElaboratedType(
- ElaboratedTypeKeyword::None, nullptr, T, nullptr));
-
- QualType ElTy = S.getElaboratedType(ElaboratedTypeKeyword::None, *SS, T);
- if (!WantNontrivialTypeSourceInfo)
- return ParsedType::make(ElTy);
-
- TypeLocBuilder Builder;
- Builder.pushTypeSpec(T).setNameLoc(NameLoc);
- ElaboratedTypeLoc ElabTL = Builder.push<ElaboratedTypeLoc>(ElTy);
- ElabTL.setElaboratedKeywordLoc(SourceLocation());
- ElabTL.setQualifierLoc(SS->getWithLocInContext(S.Context));
- return S.CreateParsedType(ElTy, Builder.getTypeSourceInfo(S.Context, ElTy));
-}
-
ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
Scope *S, CXXScopeSpec *SS, bool isClassName,
bool HasTrailingDot, ParsedType ObjectTypePtr,
@@ -348,9 +307,10 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
if (AllowImplicitTypename == ImplicitTypenameContext::No)
return nullptr;
SourceLocation QualifiedLoc = SS->getRange().getBegin();
- auto DB =
- DiagCompat(QualifiedLoc, diag_compat::implicit_typename)
- << NestedNameSpecifier::Create(Context, SS->getScopeRep(), &II);
+ // FIXME: Defer the diagnostic after we build the type and use it.
+ auto DB = DiagCompat(QualifiedLoc, diag_compat::implicit_typename)
+ << Context.getDependentNameType(ElaboratedTypeKeyword::None,
+ SS->getScopeRep(), &II);
if (!getLangOpts().CPlusPlus20)
DB << FixItHint::CreateInsertion(QualifiedLoc, "typename ");
}
@@ -430,7 +390,7 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
bool MemberOfUnknownSpecialization;
UnqualifiedId TemplateName;
TemplateName.setIdentifier(NewII, NameLoc);
- NestedNameSpecifier *NNS = Correction.getCorrectionSpecifier();
+ NestedNameSpecifier NNS = Correction.getCorrectionSpecifier();
CXXScopeSpec NewSS, *NewSSPtr = SS;
if (SS && NNS) {
NewSS.MakeTrivial(Context, NNS, SourceRange(NameLoc));
@@ -530,20 +490,78 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
assert(IIDecl && "Didn't find decl");
- QualType T;
+ TypeLocBuilder TLB;
if (TypeDecl *TD = dyn_cast<TypeDecl>(IIDecl)) {
- // C++ [class.qual]p2: A lookup that would find the injected-class-name
- // instead names the constructors of the class, except when naming a class.
- // This is ill-formed when we're not actually forming a ctor or dtor name.
- T = getTypeDeclType(LookupCtx,
- IsImplicitTypename ? DiagCtorKind::Implicit
- : DiagCtorKind::None,
- TD, NameLoc);
- } else if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) {
+ checkTypeDeclType(LookupCtx,
+ IsImplicitTypename ? DiagCtorKind::Implicit
+ : DiagCtorKind::None,
+ TD, NameLoc);
+ QualType T;
+ if (FoundUsingShadow) {
+ T = Context.getUsingType(ElaboratedTypeKeyword::None,
+ SS ? SS->getScopeRep() : std::nullopt,
+ FoundUsingShadow);
+ if (!WantNontrivialTypeSourceInfo)
+ return ParsedType::make(T);
+ TLB.push<UsingTypeLoc>(T).set(/*ElaboratedKeywordLoc=*/SourceLocation(),
+ SS ? SS->getWithLocInContext(Context)
+ : NestedNameSpecifierLoc(),
+ NameLoc);
+ } else if (auto *Tag = dyn_cast<TagDecl>(TD)) {
+ T = Context.getTagType(ElaboratedTypeKeyword::None,
+ SS ? SS->getScopeRep() : std::nullopt, Tag,
+ /*OwnsTag=*/false);
+ if (!WantNontrivialTypeSourceInfo)
+ return ParsedType::make(T);
+ auto TL = TLB.push<TagTypeLoc>(T);
+ TL.setElaboratedKeywordLoc(SourceLocation());
+ TL.setQualifierLoc(SS ? SS->getWithLocInContext(Context)
+ : NestedNameSpecifierLoc());
+ TL.setNameLoc(NameLoc);
+ } else if (auto *TN = dyn_cast<TypedefNameDecl>(TD);
+ TN && !isa<ObjCTypeParamDecl>(TN)) {
+ T = Context.getTypedefType(ElaboratedTypeKeyword::None,
+ SS ? SS->getScopeRep() : std::nullopt, TN);
+ if (!WantNontrivialTypeSourceInfo)
+ return ParsedType::make(T);
+ TLB.push<TypedefTypeLoc>(T).set(
+ /*ElaboratedKeywordLoc=*/SourceLocation(),
+ SS ? SS->getWithLocInContext(Context) : NestedNameSpecifierLoc(),
+ NameLoc);
+ } else if (auto *UD = dyn_cast<UnresolvedUsingTypenameDecl>(TD)) {
+ T = Context.getUnresolvedUsingType(ElaboratedTypeKeyword::None,
+ SS ? SS->getScopeRep() : std::nullopt,
+ UD);
+ if (!WantNontrivialTypeSourceInfo)
+ return ParsedType::make(T);
+ TLB.push<UnresolvedUsingTypeLoc>(T).set(
+ /*ElaboratedKeywordLoc=*/SourceLocation(),
+ SS ? SS->getWithLocInContext(Context) : NestedNameSpecifierLoc(),
+ NameLoc);
+ } else {
+ T = Context.getTypeDeclType(TD);
+ if (!WantNontrivialTypeSourceInfo)
+ return ParsedType::make(T);
+ if (isa<ObjCTypeParamType>(T))
+ TLB.push<ObjCTypeParamTypeLoc>(T).setNameLoc(NameLoc);
+ else
+ TLB.pushTypeSpec(T).setNameLoc(NameLoc);
+ }
+ return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T));
+ }
+ if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) {
(void)DiagnoseUseOfDecl(IDecl, NameLoc);
- if (!HasTrailingDot)
- T = Context.getObjCInterfaceType(IDecl);
- FoundUsingShadow = nullptr; // FIXME: Target must be a TypeDecl.
+ if (!HasTrailingDot) {
+ // FIXME: Support UsingType for this case.
+ QualType T = Context.getObjCInterfaceType(IDecl);
+ if (!WantNontrivialTypeSourceInfo)
+ return ParsedType::make(T);
+ auto TL = TLB.push<ObjCInterfaceTypeLoc>(T);
+ TL.setNameLoc(NameLoc);
+ // FIXME: Pass in this source location.
+ TL.setNameEndLoc(NameLoc);
+ return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T));
+ }
} else if (auto *UD = dyn_cast<UnresolvedUsingIfExistsDecl>(IIDecl)) {
(void)DiagnoseUseOfDecl(UD, NameLoc);
// Recover with 'int'
@@ -551,41 +569,38 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
} else if (AllowDeducedTemplate) {
if (auto *TD = getAsTypeTemplateDecl(IIDecl)) {
assert(!FoundUsingShadow || FoundUsingShadow->getTargetDecl() == TD);
+ // FIXME: Support UsingType here.
TemplateName Template = Context.getQualifiedTemplateName(
- SS ? SS->getScopeRep() : nullptr, /*TemplateKeyword=*/false,
+ SS ? SS->getScopeRep() : std::nullopt, /*TemplateKeyword=*/false,
FoundUsingShadow ? TemplateName(FoundUsingShadow) : TemplateName(TD));
- T = Context.getDeducedTemplateSpecializationType(Template, QualType(),
- false);
- // Don't wrap in a further UsingType.
- FoundUsingShadow = nullptr;
+ QualType T = Context.getDeducedTemplateSpecializationType(
+ ElaboratedTypeKeyword::None, Template, QualType(), false);
+ auto TL = TLB.push<DeducedTemplateSpecializationTypeLoc>(T);
+ TL.setElaboratedKWLoc(SourceLocation());
+ TL.setNameLoc(NameLoc);
+ TL.setQualifierLoc(SS ? SS->getWithLocInContext(Context)
+ : NestedNameSpecifierLoc());
+ return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T));
}
}
- if (T.isNull()) {
- // If it's not plausibly a type, suppress diagnostics.
- Result.suppressDiagnostics();
- return nullptr;
- }
-
- if (FoundUsingShadow)
- T = Context.getUsingType(FoundUsingShadow, T);
-
- return buildNamedType(*this, SS, T, NameLoc, WantNontrivialTypeSourceInfo);
+ // As it's not plausibly a type, suppress diagnostics.
+ Result.suppressDiagnostics();
+ return nullptr;
}
// Builds a fake NNS for the given decl context.
-static NestedNameSpecifier *
+static NestedNameSpecifier
synthesizeCurrentNestedNameSpecifier(ASTContext &Context, DeclContext *DC) {
for (;; DC = DC->getLookupParent()) {
DC = DC->getPrimaryContext();
auto *ND = dyn_cast<NamespaceDecl>(DC);
if (ND && !ND->isInline() && !ND->isAnonymousNamespace())
- return NestedNameSpecifier::Create(Context, nullptr, ND);
+ return NestedNameSpecifier(Context, ND, std::nullopt);
if (auto *RD = dyn_cast<CXXRecordDecl>(DC))
- return NestedNameSpecifier::Create(Context, nullptr,
- RD->getTypeForDecl());
+ return NestedNameSpecifier(Context.getCanonicalTagType(RD)->getTypePtr());
if (isa<TranslationUnitDecl>(DC))
- return NestedNameSpecifier::GlobalSpecifier(Context);
+ return NestedNameSpecifier::getGlobal();
}
llvm_unreachable("something isn't in TU scope?");
}
@@ -610,7 +625,7 @@ ParsedType Sema::ActOnMSVCUnknownTypeName(const IdentifierInfo &II,
bool IsTemplateTypeArg) {
assert(getLangOpts().MSVCCompat && "shouldn't be called in non-MSVC mode");
- NestedNameSpecifier *NNS = nullptr;
+ NestedNameSpecifier NNS = std::nullopt;
if (IsTemplateTypeArg && getCurScope()->isTemplateParamScope()) {
// If we weren't able to parse a default template argument, delay lookup
// until instantiation time by making a non-dependent DependentTypeName. We
@@ -625,7 +640,7 @@ ParsedType Sema::ActOnMSVCUnknownTypeName(const IdentifierInfo &II,
findRecordWithDependentBasesOfEnclosingMethod(CurContext)) {
// Build a DependentNameType that will perform lookup into RD at
// instantiation time.
- NNS = NestedNameSpecifier::Create(Context, nullptr, RD->getTypeForDecl());
+ NNS = NestedNameSpecifier(Context.getCanonicalTagType(RD)->getTypePtr());
// Diagnose that this identifier was undeclared, and retry the lookup during
// template instantiation.
@@ -678,19 +693,22 @@ DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) {
}
bool Sema::isMicrosoftMissingTypename(const CXXScopeSpec *SS, Scope *S) {
- if (CurContext->isRecord()) {
- if (SS->getScopeRep()->getKind() == NestedNameSpecifier::Super)
- return true;
-
- const Type *Ty = SS->getScopeRep()->getAsType();
+ if (!CurContext->isRecord())
+ return CurContext->isFunctionOrMethod() || S->isFunctionPrototypeScope();
- CXXRecordDecl *RD = cast<CXXRecordDecl>(CurContext);
- for (const auto &Base : RD->bases())
- if (Ty && Context.hasSameUnqualifiedType(QualType(Ty, 1), Base.getType()))
+ switch (SS->getScopeRep().getKind()) {
+ case NestedNameSpecifier::Kind::Super:
+ return true;
+ case NestedNameSpecifier::Kind::Type: {
+ QualType T(SS->getScopeRep().getAsType(), 0);
+ for (const auto &Base : cast<CXXRecordDecl>(CurContext)->bases())
+ if (Context.hasSameUnqualifiedType(T, Base.getType()))
return true;
+ [[fallthrough]];
+ }
+ default:
return S->isFunctionPrototypeScope();
}
- return CurContext->isFunctionOrMethod() || S->isFunctionPrototypeScope();
}
void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II,
@@ -786,7 +804,7 @@ void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II,
Diag(IILoc, IsTemplateName ? diag::err_no_member_template
: diag::err_typename_nested_not_found)
<< II << DC << SS->getRange();
- else if (SS->isValid() && SS->getScopeRep()->containsErrors()) {
+ else if (SS->isValid() && SS->getScopeRep().containsErrors()) {
SuggestedType =
ActOnTypenameType(S, SourceLocation(), *SS, *II, IILoc).get();
} else if (isDependentScopeSpecifier(*SS)) {
@@ -794,12 +812,13 @@ void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II,
if (getLangOpts().MSVCCompat && isMicrosoftMissingTypename(SS, S))
DiagID = diag::ext_typename_missing;
+ SuggestedType =
+ ActOnTypenameType(S, SourceLocation(), *SS, *II, IILoc).get();
+
Diag(SS->getRange().getBegin(), DiagID)
- << NestedNameSpecifier::Create(Context, SS->getScopeRep(), II)
+ << GetTypeFromParser(SuggestedType)
<< SourceRange(SS->getRange().getBegin(), IILoc)
<< FixItHint::CreateInsertion(SS->getRange().getBegin(), "typename ");
- SuggestedType = ActOnTypenameType(S, SourceLocation(),
- *SS, *II, IILoc).get();
} else {
assert(SS && SS->isInvalid() &&
"Invalid scope specifier has already been diagnosed");
@@ -1156,10 +1175,34 @@ Sema::NameClassification Sema::ClassifyName(Scope *S, CXXScopeSpec &SS,
}
auto BuildTypeFor = [&](TypeDecl *Type, NamedDecl *Found) {
- QualType T = Context.getTypeDeclType(Type);
- if (const auto *USD = dyn_cast<UsingShadowDecl>(Found))
- T = Context.getUsingType(USD, T);
- return buildNamedType(*this, &SS, T, NameLoc);
+ QualType T;
+ TypeLocBuilder TLB;
+ if (const auto *USD = dyn_cast<UsingShadowDecl>(Found)) {
+ T = Context.getUsingType(ElaboratedTypeKeyword::None, SS.getScopeRep(),
+ USD);
+ TLB.push<UsingTypeLoc>(T).set(/*ElaboratedKeywordLoc=*/SourceLocation(),
+ SS.getWithLocInContext(Context), NameLoc);
+ } else {
+ T = Context.getTypeDeclType(ElaboratedTypeKeyword::None, SS.getScopeRep(),
+ Type);
+ if (isa<TagType>(T)) {
+ auto TTL = TLB.push<TagTypeLoc>(T);
+ TTL.setElaboratedKeywordLoc(SourceLocation());
+ TTL.setQualifierLoc(SS.getWithLocInContext(Context));
+ TTL.setNameLoc(NameLoc);
+ } else if (isa<TypedefType>(T)) {
+ TLB.push<TypedefTypeLoc>(T).set(
+ /*ElaboratedKeywordLoc=*/SourceLocation(),
+ SS.getWithLocInContext(Context), NameLoc);
+ } else if (isa<UnresolvedUsingType>(T)) {
+ TLB.push<UnresolvedUsingTypeLoc>(T).set(
+ /*ElaboratedKeywordLoc=*/SourceLocation(),
+ SS.getWithLocInContext(Context), NameLoc);
+ } else {
+ TLB.pushTypeSpec(T).setNameLoc(NameLoc);
+ }
+ }
+ return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T));
};
NamedDecl *FirstDecl = (*Result.begin())->getUnderlyingDecl();
@@ -2009,8 +2052,7 @@ static bool ShouldDiagnoseUnusedDecl(const LangOptions &LangOpts,
// consistent for both scalars and arrays.
Ty = Ty->getBaseElementTypeUnsafe();
- if (const TagType *TT = Ty->getAs<TagType>()) {
- const TagDecl *Tag = TT->getDecl();
+ if (const TagDecl *Tag = Ty->getAsTagDecl()) {
if (Tag->hasAttr<UnusedAttr>())
return false;
@@ -2070,7 +2112,7 @@ void Sema::DiagnoseUnusedNestedTypedefs(const RecordDecl *D) {
void Sema::DiagnoseUnusedNestedTypedefs(const RecordDecl *D,
DiagReceiverTy DiagReceiver) {
- if (D->getTypeForDecl()->isDependentType())
+ if (D->isDependentType())
return;
for (auto *TmpD : D->decls()) {
@@ -2128,8 +2170,7 @@ void Sema::DiagnoseUnusedButSetDecl(const VarDecl *VD,
if (Ty->isReferenceType() || Ty->isDependentType())
return;
- if (const TagType *TT = Ty->getAs<TagType>()) {
- const TagDecl *Tag = TT->getDecl();
+ if (const TagDecl *Tag = Ty->getAsTagDecl()) {
if (Tag->hasAttr<UnusedAttr>())
return;
// In C++, don't warn for record types that don't have WarnUnusedAttr, to
@@ -2508,7 +2549,8 @@ void Sema::MergeTypedefNameDecl(Scope *S, TypedefNameDecl *New,
}
Context.setObjCIdRedefinitionType(T);
// Install the built-in type for 'id', ignoring the current definition.
- New->setTypeForDecl(Context.getObjCIdType().getTypePtr());
+ New->setModedTypeSourceInfo(New->getTypeSourceInfo(),
+ Context.getObjCIdType());
return;
}
case 5:
@@ -2516,14 +2558,16 @@ void Sema::MergeTypedefNameDecl(Scope *S, TypedefNameDecl *New,
break;
Context.setObjCClassRedefinitionType(New->getUnderlyingType());
// Install the built-in type for 'Class', ignoring the current definition.
- New->setTypeForDecl(Context.getObjCClassType().getTypePtr());
+ New->setModedTypeSourceInfo(New->getTypeSourceInfo(),
+ Context.getObjCClassType());
return;
case 3:
if (!TypeID->isStr("SEL"))
break;
Context.setObjCSelRedefinitionType(New->getUnderlyingType());
// Install the built-in type for 'SEL', ignoring the current definition.
- New->setTypeForDecl(Context.getObjCSelType().getTypePtr());
+ New->setModedTypeSourceInfo(New->getTypeSourceInfo(),
+ Context.getObjCSelType());
return;
}
// Fall through - the typedef name was not a builtin type.
@@ -2555,7 +2599,6 @@ void Sema::MergeTypedefNameDecl(Scope *S, TypedefNameDecl *New,
!hasVisibleDefinition(OldTag, &Hidden)) {
// There is a definition of this tag, but it is not visible. Use it
// instead of our tag.
- New->setTypeForDecl(OldTD->getTypeForDecl());
if (OldTD->isModed())
New->setModedTypeSourceInfo(OldTD->getTypeSourceInfo(),
OldTD->getUnderlyingType());
@@ -2742,7 +2785,7 @@ static bool mergeAlignedAttrs(Sema &S, NamedDecl *New, Decl *Old) {
if (ValueDecl *VD = dyn_cast<ValueDecl>(New))
Ty = VD->getType();
else
- Ty = S.Context.getTagDeclType(cast<TagDecl>(New));
+ Ty = S.Context.getCanonicalTagType(cast<TagDecl>(New));
if (OldAlign == 0)
OldAlign = S.Context.getTypeAlign(Ty);
@@ -2913,8 +2956,11 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
}
static const NamedDecl *getDefinition(const Decl *D) {
- if (const TagDecl *TD = dyn_cast<TagDecl>(D))
- return TD->getDefinition();
+ if (const TagDecl *TD = dyn_cast<TagDecl>(D)) {
+ if (const auto *Def = TD->getDefinition(); Def && !Def->isBeingDefined())
+ return Def;
+ return nullptr;
+ }
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
const VarDecl *Def = VD->getDefinition();
if (Def)
@@ -5016,7 +5062,7 @@ void Sema::setTagNameForLinkagePurposes(TagDecl *TagFromDeclSpec,
// The type must match the tag exactly; no qualifiers allowed.
if (!Context.hasSameType(NewTD->getUnderlyingType(),
- Context.getTagDeclType(TagFromDeclSpec))) {
+ Context.getCanonicalTagType(TagFromDeclSpec))) {
if (getLangOpts().CPlusPlus)
Context.addTypedefNameForUnnamedTagDecl(TagFromDeclSpec, NewTD);
return;
@@ -5224,9 +5270,9 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
Record = dyn_cast<RecordDecl>(Tag);
else if (const RecordType *RT =
DS.getRepAsType().get()->getAsStructureType())
- Record = RT->getDecl();
+ Record = RT->getOriginalDecl()->getDefinitionOrSelf();
else if (const RecordType *UT = DS.getRepAsType().get()->getAsUnionType())
- Record = UT->getDecl();
+ Record = UT->getOriginalDecl()->getDefinitionOrSelf();
if (Record && getLangOpts().MicrosoftExt) {
Diag(DS.getBeginLoc(), diag::ext_ms_anonymous_record)
@@ -5754,7 +5800,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
if (RecordDecl *OwningClass = dyn_cast<RecordDecl>(Owner)) {
Anon = FieldDecl::Create(
Context, OwningClass, DS.getBeginLoc(), Record->getLocation(),
- /*IdentifierInfo=*/nullptr, Context.getTypeDeclType(Record), TInfo,
+ /*IdentifierInfo=*/nullptr, Context.getCanonicalTagType(Record), TInfo,
/*BitWidth=*/nullptr, /*Mutable=*/false,
/*InitStyle=*/ICIS_NoInit);
Anon->setAccess(AS);
@@ -5774,7 +5820,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
Anon = VarDecl::Create(Context, Owner, DS.getBeginLoc(),
Record->getLocation(), /*IdentifierInfo=*/nullptr,
- Context.getTypeDeclType(Record), TInfo, SC);
+ Context.getCanonicalTagType(Record), TInfo, SC);
if (Invalid)
Anon->setInvalidDecl();
@@ -5837,7 +5883,7 @@ Decl *Sema::BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS,
assert(TInfo && "couldn't build declarator info for anonymous struct");
auto *ParentDecl = cast<RecordDecl>(CurContext);
- QualType RecTy = Context.getTypeDeclType(Record);
+ CanQualType RecTy = Context.getCanonicalTagType(Record);
// Create a declaration for this anonymous struct.
NamedDecl *Anon =
@@ -5956,14 +6002,14 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
return DeclarationNameInfo();
// Determine the type of the class being constructed.
- QualType CurClassType = Context.getTypeDeclType(CurClass);
+ CanQualType CurClassType = Context.getCanonicalTagType(CurClass);
// FIXME: Check two things: that the template-id names the same type as
// CurClassType, and that the template-id does not occur when the name
// was qualified.
- NameInfo.setName(Context.DeclarationNames.getCXXConstructorName(
- Context.getCanonicalType(CurClassType)));
+ NameInfo.setName(
+ Context.DeclarationNames.getCXXConstructorName(CurClassType));
// FIXME: should we retrieve TypeSourceInfo?
NameInfo.setNamedTypeInfo(nullptr);
return NameInfo;
@@ -6251,8 +6297,9 @@ bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC,
// that's the case, then drop this declaration entirely.
if ((Name.getNameKind() == DeclarationName::CXXConstructorName ||
Name.getNameKind() == DeclarationName::CXXDestructorName) &&
- !Context.hasSameType(Name.getCXXNameType(),
- Context.getTypeDeclType(cast<CXXRecordDecl>(Cur))))
+ !Context.hasSameType(
+ Name.getCXXNameType(),
+ Context.getCanonicalTagType(cast<CXXRecordDecl>(Cur))))
return true;
return false;
@@ -6272,36 +6319,48 @@ bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC,
<< FixItHint::CreateRemoval(TemplateId->TemplateKWLoc);
NestedNameSpecifierLoc SpecLoc(SS.getScopeRep(), SS.location_data());
- do {
- if (TypeLoc TL = SpecLoc.getTypeLoc()) {
- if (SourceLocation TemplateKeywordLoc = TL.getTemplateKeywordLoc();
- TemplateKeywordLoc.isValid())
- Diag(Loc, diag::ext_template_after_declarative_nns)
- << FixItHint::CreateRemoval(TemplateKeywordLoc);
- }
-
- if (const Type *T = SpecLoc.getNestedNameSpecifier()->getAsType()) {
- if (const auto *TST = T->getAsAdjusted<TemplateSpecializationType>()) {
- // C++23 [expr.prim.id.qual]p3:
- // [...] If a nested-name-specifier N is declarative and has a
- // simple-template-id with a template argument list A that involves a
- // template parameter, let T be the template nominated by N without A.
- // T shall be a class template.
- if (TST->isDependentType() && TST->isTypeAlias())
- Diag(Loc, diag::ext_alias_template_in_declarative_nns)
- << SpecLoc.getLocalSourceRange();
- } else if (T->isDecltypeType() || T->getAsAdjusted<PackIndexingType>()) {
- // C++23 [expr.prim.id.qual]p2:
- // [...] A declarative nested-name-specifier shall not have a
- // computed-type-specifier.
- //
- // CWG2858 changed this from 'decltype-specifier' to
- // 'computed-type-specifier'.
- Diag(Loc, diag::err_computed_type_in_declarative_nns)
- << T->isDecltypeType() << SpecLoc.getTypeLoc().getSourceRange();
- }
+ for (TypeLoc TL = SpecLoc.getAsTypeLoc(), NextTL; TL;
+ TL = std::exchange(NextTL, TypeLoc())) {
+ SourceLocation TemplateKeywordLoc;
+ switch (TL.getTypeLocClass()) {
+ case TypeLoc::TemplateSpecialization: {
+ auto TST = TL.castAs<TemplateSpecializationTypeLoc>();
+ TemplateKeywordLoc = TST.getTemplateKeywordLoc();
+ if (auto *T = TST.getTypePtr(); T->isDependentType() && T->isTypeAlias())
+ Diag(Loc, diag::ext_alias_template_in_declarative_nns)
+ << TST.getLocalSourceRange();
+ break;
+ }
+ case TypeLoc::Decltype:
+ case TypeLoc::PackIndexing: {
+ const Type *T = TL.getTypePtr();
+ // C++23 [expr.prim.id.qual]p2:
+ // [...] A declarative nested-name-specifier shall not have a
+ // computed-type-specifier.
+ //
+ // CWG2858 changed this from 'decltype-specifier' to
+ // 'computed-type-specifier'.
+ Diag(Loc, diag::err_computed_type_in_declarative_nns)
+ << T->isDecltypeType() << TL.getSourceRange();
+ break;
}
- } while ((SpecLoc = SpecLoc.getPrefix()));
+ case TypeLoc::DependentName:
+ NextTL =
+ TL.castAs<DependentNameTypeLoc>().getQualifierLoc().getAsTypeLoc();
+ break;
+ case TypeLoc::DependentTemplateSpecialization: {
+ auto TST = TL.castAs<DependentTemplateSpecializationTypeLoc>();
+ TemplateKeywordLoc = TST.getTemplateKeywordLoc();
+ NextTL = TST.getQualifierLoc().getAsTypeLoc();
+ break;
+ }
+ default:
+ break;
+ }
+ if (TemplateKeywordLoc.isValid())
+ Diag(Loc, diag::ext_template_after_declarative_nns)
+ << FixItHint::CreateRemoval(TemplateKeywordLoc);
+ }
return false;
}
@@ -9040,9 +9099,8 @@ bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
// We really want to find the base class destructor here.
- QualType T = Context.getTypeDeclType(BaseRecord);
- CanQualType CT = Context.getCanonicalType(T);
- Name = Context.DeclarationNames.getCXXDestructorName(CT);
+ Name = Context.DeclarationNames.getCXXDestructorName(
+ Context.getCanonicalTagType(BaseRecord));
}
for (NamedDecl *BaseND : BaseRecord->lookup(Name)) {
@@ -9728,7 +9786,8 @@ static void checkIsValidOpenCLKernelParameter(
// At this point we already handled everything except of a RecordType.
assert(PT->isRecordType() && "Unexpected type.");
- const RecordDecl *PD = PT->castAs<RecordType>()->getDecl();
+ const RecordDecl *PD =
+ PT->castAs<RecordType>()->getOriginalDecl()->getDefinitionOrSelf();
VisitStack.push_back(PD);
assert(VisitStack.back() && "First decl null?");
@@ -9756,7 +9815,9 @@ static void checkIsValidOpenCLKernelParameter(
"Unexpected type.");
const Type *FieldRecTy = FieldTy->getPointeeOrArrayElementType();
- RD = FieldRecTy->castAs<RecordType>()->getDecl();
+ RD = FieldRecTy->castAs<RecordType>()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf();
} else {
RD = cast<RecordDecl>(Next);
}
@@ -10763,7 +10824,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// redeclaration lookup found nothing at all. Diagnose that now;
// nothing will diagnose that error later.
if (isFriend &&
- (D.getCXXScopeSpec().getScopeRep()->isDependent() ||
+ (D.getCXXScopeSpec().getScopeRep().isDependent() ||
(!Previous.empty() && CurContext->isDependentContext()))) {
// ignore these
} else if (NewFD->isCPUDispatchMultiVersion() ||
@@ -12267,11 +12328,11 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
// template struct A<B>;
if (NewFD->getFriendObjectKind() == Decl::FriendObjectKind::FOK_None ||
!Destructor->getFunctionObjectParameterType()->isDependentType()) {
- CXXRecordDecl *Record = Destructor->getParent();
- QualType ClassType = Context.getTypeDeclType(Record);
+ CanQualType ClassType =
+ Context.getCanonicalTagType(Destructor->getParent());
- DeclarationName Name = Context.DeclarationNames.getCXXDestructorName(
- Context.getCanonicalType(ClassType));
+ DeclarationName Name =
+ Context.DeclarationNames.getCXXDestructorName(ClassType);
if (NewFD->getDeclName() != Name) {
Diag(NewFD->getLocation(), diag::err_destructor_name);
NewFD->setInvalidDecl();
@@ -13275,7 +13336,8 @@ struct DiagNonTrivalCUnionDefaultInitializeVisitor
}
void visitStruct(QualType QT, const FieldDecl *FD, bool InNonTrivialUnion) {
- const RecordDecl *RD = QT->castAs<RecordType>()->getDecl();
+ const RecordDecl *RD =
+ QT->castAs<RecordType>()->getOriginalDecl()->getDefinitionOrSelf();
if (RD->isUnion()) {
if (OrigLoc.isValid()) {
bool IsUnion = false;
@@ -13341,7 +13403,8 @@ struct DiagNonTrivalCUnionDestructedTypeVisitor
}
void visitStruct(QualType QT, const FieldDecl *FD, bool InNonTrivialUnion) {
- const RecordDecl *RD = QT->castAs<RecordType>()->getDecl();
+ const RecordDecl *RD =
+ QT->castAs<RecordType>()->getOriginalDecl()->getDefinitionOrSelf();
if (RD->isUnion()) {
if (OrigLoc.isValid()) {
bool IsUnion = false;
@@ -13406,7 +13469,8 @@ struct DiagNonTrivalCUnionCopyVisitor
}
void visitStruct(QualType QT, const FieldDecl *FD, bool InNonTrivialUnion) {
- const RecordDecl *RD = QT->castAs<RecordType>()->getDecl();
+ const RecordDecl *RD =
+ QT->castAs<RecordType>()->getOriginalDecl()->getDefinitionOrSelf();
if (RD->isUnion()) {
if (OrigLoc.isValid()) {
bool IsUnion = false;
@@ -14379,7 +14443,9 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) {
if (getLangOpts().CPlusPlus && Var->hasLocalStorage()) {
if (const RecordType *Record
= Context.getBaseElementType(Type)->getAs<RecordType>()) {
- CXXRecordDecl *CXXRecord = cast<CXXRecordDecl>(Record->getDecl());
+ CXXRecordDecl *CXXRecord =
+ cast<CXXRecordDecl>(Record->getOriginalDecl())
+ ->getDefinitionOrSelf();
// Mark the function (if we're in one) for further checking even if the
// looser rules of C++11 do not require such checks, so that we can
// diagnose incompatibilities with C++98.
@@ -17454,6 +17520,7 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
// FIXME: Check member specializations more carefully.
bool isMemberSpecialization = false;
+ bool IsInjectedClassName = false;
bool Invalid = false;
// We only need to do this matching if we have template parameters
@@ -17904,8 +17971,7 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
// see http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#407
if (getLangOpts().CPlusPlus) {
if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(PrevDecl)) {
- if (const TagType *TT = TD->getUnderlyingType()->getAs<TagType>()) {
- TagDecl *Tag = TT->getDecl();
+ if (TagDecl *Tag = TD->getUnderlyingType()->getAsTagDecl()) {
if (Tag->getDeclName() == Name &&
Tag->getDeclContext()->getRedeclContext()
->Equals(TD->getDeclContext()->getRedeclContext())) {
@@ -17915,6 +17981,15 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
Previous.resolveKind();
}
}
+ } else if (auto *RD = dyn_cast<CXXRecordDecl>(PrevDecl);
+ RD && RD->isInjectedClassName()) {
+ // If lookup found the injected class name, the previous declaration is
+ // the class being injected into.
+ PrevDecl = cast<TagDecl>(RD->getDeclContext());
+ Previous.clear();
+ Previous.addDecl(PrevDecl);
+ Previous.resolveKind();
+ IsInjectedClassName = true;
}
}
@@ -18038,78 +18113,79 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
// Diagnose attempts to redefine a tag.
if (TUK == TagUseKind::Definition) {
- if (NamedDecl *Def = PrevTagDecl->getDefinition()) {
- // If we're defining a specialization and the previous definition
- // is from an implicit instantiation, don't emit an error
- // here; we'll catch this in the general case below.
- bool IsExplicitSpecializationAfterInstantiation = false;
- if (isMemberSpecialization) {
- if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Def))
- IsExplicitSpecializationAfterInstantiation =
- RD->getTemplateSpecializationKind() !=
- TSK_ExplicitSpecialization;
- else if (EnumDecl *ED = dyn_cast<EnumDecl>(Def))
- IsExplicitSpecializationAfterInstantiation =
- ED->getTemplateSpecializationKind() !=
- TSK_ExplicitSpecialization;
- }
-
- // Note that clang allows ODR-like semantics for ObjC/C, i.e., do
- // not keep more that one definition around (merge them). However,
- // ensure the decl passes the structural compatibility check in
- // C11 6.2.7/1 (or 6.1.2.6/1 in C89).
- NamedDecl *Hidden = nullptr;
- if (SkipBody &&
- (!hasVisibleDefinition(Def, &Hidden) || getLangOpts().C23)) {
- // There is a definition of this tag, but it is not visible. We
- // explicitly make use of C++'s one definition rule here, and
- // assume that this definition is identical to the hidden one
- // we already have. Make the existing definition visible and
- // use it in place of this one.
- if (!getLangOpts().CPlusPlus) {
- // Postpone making the old definition visible until after we
- // complete parsing the new one and do the structural
- // comparison.
- SkipBody->CheckSameAsPrevious = true;
- SkipBody->New = createTagFromNewDecl();
- SkipBody->Previous = Def;
-
- ProcessDeclAttributeList(S, SkipBody->New, Attrs);
- return Def;
- } else {
- SkipBody->ShouldSkip = true;
- SkipBody->Previous = Def;
- makeMergedDefinitionVisible(Hidden);
- // Carry on and handle it like a normal definition. We'll
- // skip starting the definition later.
- }
- } else if (!IsExplicitSpecializationAfterInstantiation) {
- // A redeclaration in function prototype scope in C isn't
- // visible elsewhere, so merely issue a warning.
- if (!getLangOpts().CPlusPlus && S->containedInPrototypeScope())
- Diag(NameLoc, diag::warn_redefinition_in_param_list) << Name;
- else
- Diag(NameLoc, diag::err_redefinition) << Name;
- notePreviousDefinition(Def,
- NameLoc.isValid() ? NameLoc : KWLoc);
- // If this is a redefinition, recover by making this
- // struct be anonymous, which will make any later
- // references get the previous definition.
- Name = nullptr;
- Previous.clear();
- Invalid = true;
- }
- } else {
+ if (TagDecl *Def = PrevTagDecl->getDefinition()) {
// If the type is currently being defined, complain
// about a nested redefinition.
- auto *TD = Context.getTagDeclType(PrevTagDecl)->getAsTagDecl();
- if (TD->isBeingDefined()) {
+ if (Def->isBeingDefined()) {
Diag(NameLoc, diag::err_nested_redefinition) << Name;
Diag(PrevTagDecl->getLocation(),
diag::note_previous_definition);
Name = nullptr;
Previous.clear();
Invalid = true;
+ } else {
+ // If we're defining a specialization and the previous
+ // definition is from an implicit instantiation, don't emit an
+ // error here; we'll catch this in the general case below.
+ bool IsExplicitSpecializationAfterInstantiation = false;
+ if (isMemberSpecialization) {
+ if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Def))
+ IsExplicitSpecializationAfterInstantiation =
+ RD->getTemplateSpecializationKind() !=
+ TSK_ExplicitSpecialization;
+ else if (EnumDecl *ED = dyn_cast<EnumDecl>(Def))
+ IsExplicitSpecializationAfterInstantiation =
+ ED->getTemplateSpecializationKind() !=
+ TSK_ExplicitSpecialization;
+ }
+
+ // Note that clang allows ODR-like semantics for ObjC/C, i.e.,
+ // do not keep more that one definition around (merge them).
+ // However, ensure the decl passes the structural compatibility
+ // check in C11 6.2.7/1 (or 6.1.2.6/1 in C89).
+ NamedDecl *Hidden = nullptr;
+ if (SkipBody && (!hasVisibleDefinition(Def, &Hidden) ||
+ getLangOpts().C23)) {
+ // There is a definition of this tag, but it is not visible.
+ // We explicitly make use of C++'s one definition rule here,
+ // and assume that this definition is identical to the hidden
+ // one we already have. Make the existing definition visible
+ // and use it in place of this one.
+ if (!getLangOpts().CPlusPlus) {
+ // Postpone making the old definition visible until after we
+ // complete parsing the new one and do the structural
+ // comparison.
+ SkipBody->CheckSameAsPrevious = true;
+ SkipBody->New = createTagFromNewDecl();
+ SkipBody->Previous = Def;
+
+ ProcessDeclAttributeList(S, SkipBody->New, Attrs);
+ return Def;
+ } else {
+ SkipBody->ShouldSkip = true;
+ SkipBody->Previous = Def;
+ makeMergedDefinitionVisible(Hidden);
+ // Carry on and handle it like a normal definition. We'll
+ // skip starting the definition later.
+ }
+ } else if (!IsExplicitSpecializationAfterInstantiation) {
+ // A redeclaration in function prototype scope in C isn't
+ // visible elsewhere, so merely issue a warning.
+ if (!getLangOpts().CPlusPlus &&
+ S->containedInPrototypeScope())
+ Diag(NameLoc, diag::warn_redefinition_in_param_list)
+ << Name;
+ else
+ Diag(NameLoc, diag::err_redefinition) << Name;
+ notePreviousDefinition(Def,
+ NameLoc.isValid() ? NameLoc : KWLoc);
+ // If this is a redefinition, recover by making this
+ // struct be anonymous, which will make any later
+ // references get the previous definition.
+ Name = nullptr;
+ Previous.clear();
+ Invalid = true;
+ }
}
}
@@ -18280,14 +18356,14 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
(IsTypeSpecifier || IsTemplateParamOrArg) &&
TUK == TagUseKind::Definition) {
Diag(New->getLocation(), diag::err_type_defined_in_type_specifier)
- << Context.getTagDeclType(New);
+ << Context.getCanonicalTagType(New);
Invalid = true;
}
if (!Invalid && getLangOpts().CPlusPlus && TUK == TagUseKind::Definition &&
DC->getDeclKind() == Decl::Enum) {
Diag(New->getLocation(), diag::err_type_defined_in_enum)
- << Context.getTagDeclType(New);
+ << Context.getCanonicalTagType(New);
Invalid = true;
}
@@ -18368,7 +18444,8 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
// In C23 mode, if the declaration is complete, we do not want to
// diagnose.
if (!getLangOpts().C23 || TUK != TagUseKind::Definition)
- Diag(Loc, diag::warn_decl_in_param_list) << Context.getTagDeclType(New);
+ Diag(Loc, diag::warn_decl_in_param_list)
+ << Context.getCanonicalTagType(New);
}
}
@@ -18400,7 +18477,7 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
AddPragmaAttributes(S, New);
// If this has an identifier, add it to the scope stack.
- if (TUK == TagUseKind::Friend) {
+ if (TUK == TagUseKind::Friend || IsInjectedClassName) {
// We might be replacing an existing declaration in the lookup tables;
// if so, borrow its access specifier.
if (PrevDecl)
@@ -18516,14 +18593,12 @@ void Sema::ActOnStartCXXMemberDeclarations(
// as if it were a public member name.
CXXRecordDecl *InjectedClassName = CXXRecordDecl::Create(
Context, Record->getTagKind(), CurContext, Record->getBeginLoc(),
- Record->getLocation(), Record->getIdentifier(),
- /*PrevDecl=*/nullptr,
- /*DelayTypeCreation=*/true);
- Context.getTypeDeclType(InjectedClassName, Record);
+ Record->getLocation(), Record->getIdentifier());
InjectedClassName->setImplicit();
InjectedClassName->setAccess(AS_public);
if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate())
InjectedClassName->setDescribedClassTemplate(Template);
+
PushOnScopeChains(InjectedClassName, S);
assert(InjectedClassName->isInjectedClassName() &&
"Broken injected-class-name");
@@ -18953,7 +19028,7 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
if (!InvalidDecl && getLangOpts().CPlusPlus) {
if (Record->isUnion()) {
if (const RecordType *RT = EltTy->getAs<RecordType>()) {
- CXXRecordDecl* RDecl = cast<CXXRecordDecl>(RT->getDecl());
+ CXXRecordDecl *RDecl = cast<CXXRecordDecl>(RT->getOriginalDecl());
if (RDecl->getDefinition()) {
// C++ [class.union]p1: An object of a class with a non-trivial
// constructor, a non-trivial copy constructor, a non-trivial
@@ -19019,7 +19094,8 @@ bool Sema::CheckNontrivialField(FieldDecl *FD) {
QualType EltTy = Context.getBaseElementType(FD->getType());
if (const RecordType *RT = EltTy->getAs<RecordType>()) {
- CXXRecordDecl *RDecl = cast<CXXRecordDecl>(RT->getDecl());
+ CXXRecordDecl *RDecl =
+ cast<CXXRecordDecl>(RT->getOriginalDecl())->getDefinitionOrSelf();
if (RDecl->getDefinition()) {
// We check for copy constructors before constructors
// because otherwise we'll never get complaints about
@@ -19342,7 +19418,7 @@ bool Sema::EntirelyFunctionPointers(const RecordDecl *Record) {
}
// If a member is a struct entirely of function pointers, that counts too.
if (const RecordType *RT = FieldType->getAs<RecordType>()) {
- const RecordDecl *Record = RT->getDecl();
+ const RecordDecl *Record = RT->getOriginalDecl()->getDefinitionOrSelf();
if (Record->isStruct() && EntirelyFunctionPointers(Record))
return true;
}
@@ -19500,7 +19576,9 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
EnclosingDecl->setInvalidDecl();
continue;
} else if (const RecordType *FDTTy = FDTy->getAs<RecordType>()) {
- if (Record && FDTTy->getDecl()->hasFlexibleArrayMember()) {
+ if (Record && FDTTy->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->hasFlexibleArrayMember()) {
// A type which contains a flexible array member is considered to be a
// flexible array member.
Record->setHasFlexibleArrayMember(true);
@@ -19526,9 +19604,10 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
// Ivars can not have abstract class types
FD->setInvalidDecl();
}
- if (Record && FDTTy->getDecl()->hasObjectMember())
+ const RecordDecl *RD = FDTTy->getOriginalDecl()->getDefinitionOrSelf();
+ if (Record && RD->hasObjectMember())
Record->setHasObjectMember(true);
- if (Record && FDTTy->getDecl()->hasVolatileMember())
+ if (Record && RD->hasVolatileMember())
Record->setHasVolatileMember(true);
} else if (FDTy->isObjCObjectType()) {
/// A field cannot be an Objective-c object
@@ -19559,8 +19638,10 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
Record->setHasObjectMember(true);
else if (Context.getAsArrayType(FD->getType())) {
QualType BaseType = Context.getBaseElementType(FD->getType());
- if (BaseType->isRecordType() &&
- BaseType->castAs<RecordType>()->getDecl()->hasObjectMember())
+ if (BaseType->isRecordType() && BaseType->castAs<RecordType>()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->hasObjectMember())
Record->setHasObjectMember(true);
else if (BaseType->isObjCObjectPointerType() ||
BaseType.isObjCGCStrong())
@@ -19593,7 +19674,9 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
}
if (const auto *RT = FT->getAs<RecordType>()) {
- if (RT->getDecl()->getArgPassingRestrictions() ==
+ if (RT->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->getArgPassingRestrictions() ==
RecordArgPassingKind::CanNeverPassInRegs)
Record->setArgPassingRestrictions(
RecordArgPassingKind::CanNeverPassInRegs);
@@ -20359,7 +20442,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange,
Decl *EnumDeclX, ArrayRef<Decl *> Elements, Scope *S,
const ParsedAttributesView &Attrs) {
EnumDecl *Enum = cast<EnumDecl>(EnumDeclX);
- QualType EnumType = Context.getTypeDeclType(Enum);
+ CanQualType EnumType = Context.getCanonicalTagType(Enum);
ProcessDeclAttributeList(S, Enum, Attrs);
ProcessAPINotes(Enum);
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 7ebb53318702c..19694d8b06c38 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -177,7 +177,7 @@ static bool threadSafetyCheckIsSmartPointer(Sema &S, const RecordType* RT) {
return !Result.empty();
};
- const RecordDecl *Record = RT->getDecl();
+ const RecordDecl *Record = RT->getOriginalDecl()->getDefinitionOrSelf();
bool foundStarOperator = IsOverloadedOperatorPresent(Record, OO_Star);
bool foundArrowOperator = IsOverloadedOperatorPresent(Record, OO_Arrow);
if (foundStarOperator && foundArrowOperator)
@@ -271,7 +271,8 @@ static bool checkRecordTypeForCapability(Sema &S, QualType Ty) {
if (threadSafetyCheckIsSmartPointer(S, RT))
return true;
- return checkRecordDeclForAttr<CapabilityAttr>(RT->getDecl());
+ return checkRecordDeclForAttr<CapabilityAttr>(
+ RT->getOriginalDecl()->getDefinitionOrSelf());
}
static bool checkRecordTypeForScopedCapability(Sema &S, QualType Ty) {
@@ -284,7 +285,8 @@ static bool checkRecordTypeForScopedCapability(Sema &S, QualType Ty) {
if (RT->isIncompleteType())
return true;
- return checkRecordDeclForAttr<ScopedLockableAttr>(RT->getDecl());
+ return checkRecordDeclForAttr<ScopedLockableAttr>(
+ RT->getOriginalDecl()->getDefinitionOrSelf());
}
static bool checkTypedefTypeForCapability(QualType Ty) {
@@ -1254,8 +1256,8 @@ bool Sema::isValidPointerAttrType(QualType T, bool RefOkay) {
// The nonnull attribute, and other similar attributes, can be applied to a
// transparent union that contains a pointer type.
if (const RecordType *UT = T->getAsUnionType()) {
- if (UT && UT->getDecl()->hasAttr<TransparentUnionAttr>()) {
- RecordDecl *UD = UT->getDecl();
+ RecordDecl *UD = UT->getOriginalDecl()->getDefinitionOrSelf();
+ if (UD->hasAttr<TransparentUnionAttr>()) {
for (const auto *I : UD->fields()) {
QualType QT = I->getType();
if (QT->isAnyPointerType() || QT->isBlockPointerType())
@@ -3761,7 +3763,9 @@ static void handleFormatArgAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
}
Ty = getFunctionOrMethodResultType(D);
// replace instancetype with the class type
- auto Instancetype = S.Context.getObjCInstanceTypeDecl()->getTypeForDecl();
+ auto *Instancetype = cast<TypedefType>(S.Context.getTypedefType(
+ ElaboratedTypeKeyword::None, /*Qualifier=*/std::nullopt,
+ S.Context.getObjCInstanceTypeDecl()));
if (Ty->getAs<TypedefType>() == Instancetype)
if (auto *OMD = dyn_cast<ObjCMethodDecl>(D))
if (auto *Interface = OMD->getClassInterface())
@@ -4355,7 +4359,10 @@ static void handleTransparentUnionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
RecordDecl *RD = nullptr;
const auto *TD = dyn_cast<TypedefNameDecl>(D);
if (TD && TD->getUnderlyingType()->isUnionType())
- RD = TD->getUnderlyingType()->getAsUnionType()->getDecl();
+ RD = TD->getUnderlyingType()
+ ->getAsUnionType()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf();
else
RD = dyn_cast<RecordDecl>(D);
@@ -4708,7 +4715,7 @@ void Sema::CheckAlignasUnderalignment(Decl *D) {
if (const auto *VD = dyn_cast<ValueDecl>(D)) {
UnderlyingTy = DiagTy = VD->getType();
} else {
- UnderlyingTy = DiagTy = Context.getTagDeclType(cast<TagDecl>(D));
+ UnderlyingTy = DiagTy = Context.getCanonicalTagType(cast<TagDecl>(D));
if (const auto *ED = dyn_cast<EnumDecl>(D))
UnderlyingTy = ED->getIntegerType();
}
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index f0247f865ba40..3d2b7f021f9b5 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -10,6 +10,7 @@
//
//===----------------------------------------------------------------------===//
+#include "TypeLocBuilder.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTMutationListener.h"
@@ -1101,15 +1102,13 @@ static std::string printTemplateArgs(const PrintingPolicy &PrintingPolicy,
return std::string(OS.str());
}
-static bool lookupStdTypeTraitMember(Sema &S, LookupResult &TraitMemberLookup,
- SourceLocation Loc, StringRef Trait,
- TemplateArgumentListInfo &Args,
- unsigned DiagID) {
+static QualType getStdTrait(Sema &S, SourceLocation Loc, StringRef Trait,
+ TemplateArgumentListInfo &Args, unsigned DiagID) {
auto DiagnoseMissing = [&] {
if (DiagID)
S.Diag(Loc, DiagID) << printTemplateArgs(S.Context.getPrintingPolicy(),
Args, /*Params*/ nullptr);
- return true;
+ return QualType();
};
// FIXME: Factor out duplication with lookupPromiseType in SemaCoroutine.
@@ -1122,12 +1121,12 @@ static bool lookupStdTypeTraitMember(Sema &S, LookupResult &TraitMemberLookup,
// missing specialization, because this can only fail if the user has been
// declaring their own names in namespace std or we don't support the
// standard library implementation in use.
- LookupResult Result(S, &S.PP.getIdentifierTable().get(Trait),
- Loc, Sema::LookupOrdinaryName);
+ LookupResult Result(S, &S.PP.getIdentifierTable().get(Trait), Loc,
+ Sema::LookupOrdinaryName);
if (!S.LookupQualifiedName(Result, Std))
return DiagnoseMissing();
if (Result.isAmbiguous())
- return true;
+ return QualType();
ClassTemplateDecl *TraitTD = Result.getAsSingle<ClassTemplateDecl>();
if (!TraitTD) {
@@ -1135,28 +1134,31 @@ static bool lookupStdTypeTraitMember(Sema &S, LookupResult &TraitMemberLookup,
NamedDecl *Found = *Result.begin();
S.Diag(Loc, diag::err_std_type_trait_not_class_template) << Trait;
S.Diag(Found->getLocation(), diag::note_declared_at);
- return true;
+ return QualType();
}
// Build the template-id.
- QualType TraitTy = S.CheckTemplateIdType(TemplateName(TraitTD), Loc, Args);
+ QualType TraitTy = S.CheckTemplateIdType(ElaboratedTypeKeyword::None,
+ TemplateName(TraitTD), Loc, Args);
if (TraitTy.isNull())
- return true;
+ return QualType();
+
if (!S.isCompleteType(Loc, TraitTy)) {
if (DiagID)
S.RequireCompleteType(
Loc, TraitTy, DiagID,
printTemplateArgs(S.Context.getPrintingPolicy(), Args,
TraitTD->getTemplateParameters()));
- return true;
+ return QualType();
}
+ return TraitTy;
+}
- CXXRecordDecl *RD = TraitTy->getAsCXXRecordDecl();
+static bool lookupMember(Sema &S, CXXRecordDecl *RD,
+ LookupResult &MemberLookup) {
assert(RD && "specialization of class template is not a class?");
-
- // Look up the member of the trait type.
- S.LookupQualifiedName(TraitMemberLookup, RD);
- return TraitMemberLookup.isAmbiguous();
+ S.LookupQualifiedName(MemberLookup, RD);
+ return MemberLookup.isAmbiguous();
}
static TemplateArgumentLoc
@@ -1178,17 +1180,20 @@ static IsTupleLike isTupleLike(Sema &S, SourceLocation Loc, QualType T,
EnterExpressionEvaluationContext ContextRAII(
S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
- DeclarationName Value = S.PP.getIdentifierInfo("value");
- LookupResult R(S, Value, Loc, Sema::LookupOrdinaryName);
-
// Form template argument list for tuple_size<T>.
TemplateArgumentListInfo Args(Loc, Loc);
Args.addArgument(getTrivialTypeTemplateArgument(S, Loc, T));
+ QualType TraitTy = getStdTrait(S, Loc, "tuple_size", Args, /*DiagID=*/0);
+ if (TraitTy.isNull())
+ return IsTupleLike::NotTupleLike;
+
+ DeclarationName Value = S.PP.getIdentifierInfo("value");
+ LookupResult R(S, Value, Loc, Sema::LookupOrdinaryName);
+
// If there's no tuple_size specialization or the lookup of 'value' is empty,
// it's not tuple-like.
- if (lookupStdTypeTraitMember(S, R, Loc, "tuple_size", Args, /*DiagID*/ 0) ||
- R.empty())
+ if (lookupMember(S, TraitTy->getAsCXXRecordDecl(), R) || R.empty())
return IsTupleLike::NotTupleLike;
// If we get this far, we've committed to the tuple interpretation, but
@@ -1228,11 +1233,15 @@ static QualType getTupleLikeElementType(Sema &S, SourceLocation Loc,
getTrivialIntegralTemplateArgument(S, Loc, S.Context.getSizeType(), I));
Args.addArgument(getTrivialTypeTemplateArgument(S, Loc, T));
+ QualType TraitTy =
+ getStdTrait(S, Loc, "tuple_element", Args,
+ diag::err_decomp_decl_std_tuple_element_not_specialized);
+ if (TraitTy.isNull())
+ return QualType();
+
DeclarationName TypeDN = S.PP.getIdentifierInfo("type");
LookupResult R(S, TypeDN, Loc, Sema::LookupOrdinaryName);
- if (lookupStdTypeTraitMember(
- S, R, Loc, "tuple_element", Args,
- diag::err_decomp_decl_std_tuple_element_not_specialized))
+ if (lookupMember(S, TraitTy->getAsCXXRecordDecl(), R))
return QualType();
auto *TD = R.getAsSingle<TypeDecl>();
@@ -1246,7 +1255,8 @@ static QualType getTupleLikeElementType(Sema &S, SourceLocation Loc,
return QualType();
}
- return S.Context.getTypeDeclType(TD);
+ NestedNameSpecifier Qualifier(TraitTy.getTypePtr());
+ return S.Context.getTypeDeclType(ElaboratedTypeKeyword::None, Qualifier, TD);
}
namespace {
@@ -1452,7 +1462,7 @@ static DeclAccessPair findDecomposableBaseClass(Sema &S, SourceLocation Loc,
}
// ... [accessible, implied by other rules] base class of E.
- S.CheckBaseClassAccess(Loc, BaseType, S.Context.getRecordType(RD),
+ S.CheckBaseClassAccess(Loc, BaseType, S.Context.getCanonicalTagType(RD),
*BestPath, diag::err_decomp_decl_inaccessible_base);
AS = BestPath->Access;
@@ -1528,8 +1538,8 @@ static bool checkMemberDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings,
const auto *RD = cast_or_null<CXXRecordDecl>(BasePair.getDecl());
if (!RD)
return true;
- QualType BaseType = S.Context.getQualifiedType(S.Context.getRecordType(RD),
- DecompType.getQualifiers());
+ QualType BaseType = S.Context.getQualifiedType(
+ S.Context.getCanonicalTagType(RD), DecompType.getQualifiers());
auto *DD = cast<DecompositionDecl>(Src);
unsigned NumFields = llvm::count_if(
@@ -2174,7 +2184,10 @@ static bool CheckConstexprCtorInitializer(Sema &SemaRef,
return false;
}
} else if (Field->isAnonymousStructOrUnion()) {
- const RecordDecl *RD = Field->getType()->castAs<RecordType>()->getDecl();
+ const RecordDecl *RD = Field->getType()
+ ->castAs<RecordType>()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf();
for (auto *I : RD->fields())
// If an anonymous union contains an anonymous struct of which any member
// is initialized, all members must be initialized.
@@ -2666,7 +2679,9 @@ void Sema::DiagnoseImmediateEscalatingReason(FunctionDecl *FD) {
return DynamicRecursiveASTVisitor::TraverseCXXConstructorDecl(Ctr);
}
- bool TraverseType(QualType T) override { return true; }
+ bool TraverseType(QualType T, bool TraverseQualifier) override {
+ return true;
+ }
bool VisitBlockExpr(BlockExpr *T) override { return true; }
} Visitor(*this, FD);
@@ -2969,7 +2984,8 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class,
NoteIndirectBases(Context, IndirectBaseTypes, NewBaseType);
if (const RecordType *Record = NewBaseType->getAs<RecordType>()) {
- const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getOriginalDecl())
+ ->getDefinitionOrSelf();
if (Class->isInterface() &&
(!RD->isInterfaceLike() ||
KnownBase->getAccessSpecifier() != AS_public)) {
@@ -3050,7 +3066,7 @@ bool Sema::IsDerivedFrom(SourceLocation Loc, CXXRecordDecl *Derived,
// FIXME: In a modules build, do we need the entire path to be visible for us
// to be able to use the inheritance relationship?
- if (!isCompleteType(Loc, Context.getTypeDeclType(Derived)) &&
+ if (!isCompleteType(Loc, Context.getCanonicalTagType(Derived)) &&
!Derived->isBeingDefined())
return false;
@@ -3205,7 +3221,8 @@ std::string Sema::getAmbiguousPathsDisplayString(CXXBasePaths &Paths) {
// We haven't displayed a path to this particular base
// class subobject yet.
PathDisplayStr += "\n ";
- PathDisplayStr += Context.getTypeDeclType(Paths.getOrigin()).getAsString();
+ PathDisplayStr += QualType(Context.getCanonicalTagType(Paths.getOrigin()))
+ .getAsString();
for (CXXBasePath::const_iterator Element = Path->begin();
Element != Path->end(); ++Element)
PathDisplayStr += " -> " + Element->Base->getType().getAsString();
@@ -4245,7 +4262,7 @@ static bool FindBaseInitializer(Sema &SemaRef,
CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
/*DetectVirtual=*/false);
if (SemaRef.IsDerivedFrom(ClassDecl->getLocation(),
- SemaRef.Context.getTypeDeclType(ClassDecl),
+ SemaRef.Context.getCanonicalTagType(ClassDecl),
BaseType, Paths)) {
for (CXXBasePaths::paths_iterator Path = Paths.begin();
Path != Paths.end(); ++Path) {
@@ -4481,7 +4498,7 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
if (getLangOpts().MSVCCompat && !getLangOpts().CPlusPlus20) {
if (auto UnqualifiedBase = R.getAsSingle<ClassTemplateDecl>()) {
auto *TempSpec = cast<TemplateSpecializationType>(
- UnqualifiedBase->getInjectedClassNameSpecialization());
+ UnqualifiedBase->getCanonicalInjectedSpecializationType(Context));
TemplateName TN = TempSpec->getTemplateName();
for (auto const &Base : ClassDecl->bases()) {
auto BaseTemplate =
@@ -4545,14 +4562,29 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
}
if (BaseType.isNull()) {
- BaseType = getElaboratedType(ElaboratedTypeKeyword::None, SS,
- Context.getTypeDeclType(TyD));
MarkAnyDeclReferenced(TyD->getLocation(), TyD, /*OdrUse=*/false);
- TInfo = Context.CreateTypeSourceInfo(BaseType);
- ElaboratedTypeLoc TL = TInfo->getTypeLoc().castAs<ElaboratedTypeLoc>();
- TL.getNamedTypeLoc().castAs<TypeSpecTypeLoc>().setNameLoc(IdLoc);
- TL.setElaboratedKeywordLoc(SourceLocation());
- TL.setQualifierLoc(SS.getWithLocInContext(Context));
+
+ TypeLocBuilder TLB;
+ if (const auto *TD = dyn_cast<TagDecl>(TyD)) {
+ BaseType = Context.getTagType(ElaboratedTypeKeyword::None,
+ SS.getScopeRep(), TD, /*OwnsTag=*/false);
+ auto TL = TLB.push<TagTypeLoc>(BaseType);
+ TL.setElaboratedKeywordLoc(SourceLocation());
+ TL.setQualifierLoc(SS.getWithLocInContext(Context));
+ TL.setNameLoc(IdLoc);
+ } else if (auto *TN = dyn_cast<TypedefNameDecl>(TyD)) {
+ BaseType = Context.getTypedefType(ElaboratedTypeKeyword::None,
+ SS.getScopeRep(), TN);
+ TLB.push<TypedefTypeLoc>(BaseType).set(
+ /*ElaboratedKeywordLoc=*/SourceLocation(),
+ SS.getWithLocInContext(Context), IdLoc);
+ } else {
+ // FIXME: What else can appear here?
+ assert(SS.isEmpty());
+ BaseType = Context.getTypeDeclType(TyD);
+ TLB.pushTypeSpec(BaseType).setNameLoc(IdLoc);
+ }
+ TInfo = TLB.getTypeSourceInfo(Context, BaseType);
}
}
@@ -4661,10 +4693,12 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init,
Args = MultiExprArg(ParenList->getExprs(), ParenList->getNumExprs());
}
+ CanQualType ClassType = Context.getCanonicalTagType(ClassDecl);
+
SourceRange InitRange = Init->getSourceRange();
// Initialize the object.
- InitializedEntity DelegationEntity = InitializedEntity::InitializeDelegation(
- QualType(ClassDecl->getTypeForDecl(), 0));
+ InitializedEntity DelegationEntity =
+ InitializedEntity::InitializeDelegation(ClassType);
InitializationKind Kind =
InitList ? InitializationKind::CreateDirectList(
NameLoc, Init->getBeginLoc(), Init->getEndLoc())
@@ -4686,9 +4720,8 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init,
}
if (DelegationInit.isInvalid()) {
- DelegationInit =
- CreateRecoveryExpr(InitRange.getBegin(), InitRange.getEnd(), Args,
- QualType(ClassDecl->getTypeForDecl(), 0));
+ DelegationInit = CreateRecoveryExpr(InitRange.getBegin(),
+ InitRange.getEnd(), Args, ClassType);
if (DelegationInit.isInvalid())
return true;
} else {
@@ -4753,8 +4786,7 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
const CXXBaseSpecifier *DirectBaseSpec = nullptr;
const CXXBaseSpecifier *VirtualBaseSpec = nullptr;
if (!Dependent) {
- if (Context.hasSameUnqualifiedType(QualType(ClassDecl->getTypeForDecl(),0),
- BaseType))
+ if (declaresSameEntity(ClassDecl, BaseType->getAsCXXRecordDecl()))
return BuildDelegatingInitializer(BaseTInfo, Init, ClassDecl);
FindBaseInitializer(*this, ClassDecl, BaseType, DirectBaseSpec,
@@ -4774,7 +4806,7 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
Dependent = true;
else
return Diag(BaseLoc, diag::err_not_direct_base_or_virtual)
- << BaseType << Context.getTypeDeclType(ClassDecl)
+ << BaseType << Context.getCanonicalTagType(ClassDecl)
<< BaseTInfo->getTypeLoc().getSourceRange();
}
}
@@ -5078,9 +5110,9 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
if (FieldBaseElementType->isReferenceType()) {
SemaRef.Diag(Constructor->getLocation(),
diag::err_uninitialized_member_in_ctor)
- << (int)Constructor->isImplicit()
- << SemaRef.Context.getTagDeclType(Constructor->getParent())
- << 0 << Field->getDeclName();
+ << (int)Constructor->isImplicit()
+ << SemaRef.Context.getCanonicalTagType(Constructor->getParent()) << 0
+ << Field->getDeclName();
SemaRef.Diag(Field->getLocation(), diag::note_declared_at);
return true;
}
@@ -5088,9 +5120,9 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
if (FieldBaseElementType.isConstQualified()) {
SemaRef.Diag(Constructor->getLocation(),
diag::err_uninitialized_member_in_ctor)
- << (int)Constructor->isImplicit()
- << SemaRef.Context.getTagDeclType(Constructor->getParent())
- << 1 << Field->getDeclName();
+ << (int)Constructor->isImplicit()
+ << SemaRef.Context.getCanonicalTagType(Constructor->getParent()) << 1
+ << Field->getDeclName();
SemaRef.Diag(Field->getLocation(), diag::note_declared_at);
return true;
}
@@ -5391,7 +5423,7 @@ static void MarkBaseDestructorsReferenced(Sema &S, SourceLocation Location,
S.CheckDestructorAccess(Base.getBeginLoc(), Dtor,
S.PDiag(diag::err_access_dtor_base)
<< Base.getType() << Base.getSourceRange(),
- S.Context.getTypeDeclType(ClassDecl));
+ S.Context.getCanonicalTagType(ClassDecl));
S.MarkFunctionReferenced(Location, Dtor);
S.DiagnoseUseOfDecl(Dtor, Location);
@@ -5594,9 +5626,9 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, bool AnyErrors,
static void PopulateKeysForFields(FieldDecl *Field, SmallVectorImpl<const void*> &IdealInits) {
if (const RecordType *RT = Field->getType()->getAs<RecordType>()) {
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl();
if (RD->isAnonymousStructOrUnion()) {
- for (auto *Field : RD->fields())
+ for (auto *Field : RD->getDefinitionOrSelf()->fields())
PopulateKeysForFields(Field, IdealInits);
return;
}
@@ -5928,16 +5960,14 @@ void Sema::MarkVirtualBaseDestructorsReferenced(
if (!Dtor)
continue;
- if (CheckDestructorAccess(
- ClassDecl->getLocation(), Dtor,
- PDiag(diag::err_access_dtor_vbase)
- << Context.getTypeDeclType(ClassDecl) << VBase.getType(),
- Context.getTypeDeclType(ClassDecl)) ==
- AR_accessible) {
+ CanQualType CT = Context.getCanonicalTagType(ClassDecl);
+ if (CheckDestructorAccess(ClassDecl->getLocation(), Dtor,
+ PDiag(diag::err_access_dtor_vbase)
+ << CT << VBase.getType(),
+ CT) == AR_accessible) {
CheckDerivedToBaseConversion(
- Context.getTypeDeclType(ClassDecl), VBase.getType(),
- diag::err_access_dtor_vbase, 0, ClassDecl->getLocation(),
- SourceRange(), DeclarationName(), nullptr);
+ CT, VBase.getType(), diag::err_access_dtor_vbase, 0,
+ ClassDecl->getLocation(), SourceRange(), DeclarationName(), nullptr);
}
MarkFunctionReferenced(Location, Dtor);
@@ -6052,10 +6082,8 @@ struct AbstractUsageInfo {
bool Invalid;
AbstractUsageInfo(Sema &S, CXXRecordDecl *Record)
- : S(S), Record(Record),
- AbstractType(S.Context.getCanonicalType(
- S.Context.getTypeDeclType(Record))),
- Invalid(false) {}
+ : S(S), Record(Record),
+ AbstractType(S.Context.getCanonicalTagType(Record)), Invalid(false) {}
void DiagnoseAbstractType() {
if (Invalid) return;
@@ -6868,8 +6896,8 @@ static bool canPassInRegisters(Sema &S, CXXRecordDecl *D,
bool isAArch64 = S.Context.getTargetInfo().getTriple().isAArch64();
uint64_t TypeSize = isAArch64 ? 128 : 64;
- if (CopyCtorIsTrivial &&
- S.getASTContext().getTypeSize(D->getTypeForDecl()) <= TypeSize)
+ if (CopyCtorIsTrivial && S.getASTContext().getTypeSize(
+ S.Context.getCanonicalTagType(D)) <= TypeSize)
return true;
return false;
}
@@ -7000,7 +7028,8 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) {
if ((!dtor || (!dtor->isVirtual() && dtor->getAccess() == AS_public)) &&
!Record->hasAttr<FinalAttr>())
Diag(dtor ? dtor->getLocation() : Record->getLocation(),
- diag::warn_non_virtual_dtor) << Context.getRecordType(Record);
+ diag::warn_non_virtual_dtor)
+ << Context.getCanonicalTagType(Record);
}
if (Record->isAbstract()) {
@@ -7022,7 +7051,7 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) {
(FA->isSpelledAsSealed() ? " sealed" : " final"));
Diag(Record->getLocation(),
diag::note_final_dtor_non_final_class_silence)
- << Context.getRecordType(Record) << FA->isSpelledAsSealed();
+ << Context.getCanonicalTagType(Record) << FA->isSpelledAsSealed();
}
}
}
@@ -7177,7 +7206,7 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) {
return true;
};
EffectivelyConstexprDestructor =
- Check(QualType(Record->getTypeForDecl(), 0), Check);
+ Check(Context.getCanonicalTagType(Record), Check);
}
// Define defaulted constexpr virtual functions that override a base class
@@ -7333,7 +7362,7 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) {
NewDecls.empty() ? NewKind : DeleteKind);
Diag(Record->getLocation(),
diag::err_type_aware_allocator_missing_matching_operator)
- << FoundOperator << Context.getRecordType(Record)
+ << FoundOperator << Context.getCanonicalTagType(Record)
<< MissingOperator;
for (auto MD : NewDecls)
Diag(MD->getLocation(),
@@ -7572,7 +7601,9 @@ static bool defaultedSpecialMemberIsConstexpr(
const RecordType *BaseType = B.getType()->getAs<RecordType>();
if (!BaseType)
continue;
- CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
+ CXXRecordDecl *BaseClassDecl =
+ cast<CXXRecordDecl>(BaseType->getOriginalDecl())
+ ->getDefinitionOrSelf();
if (!specialMemberIsConstexpr(S, BaseClassDecl, CSM, 0, ConstArg,
InheritedCtor, Inherited))
return false;
@@ -7595,7 +7626,9 @@ static bool defaultedSpecialMemberIsConstexpr(
continue;
QualType BaseType = S.Context.getBaseElementType(F->getType());
if (const RecordType *RecordTy = BaseType->getAs<RecordType>()) {
- CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RecordTy->getDecl());
+ CXXRecordDecl *FieldRecDecl =
+ cast<CXXRecordDecl>(RecordTy->getOriginalDecl())
+ ->getDefinitionOrSelf();
if (!specialMemberIsConstexpr(S, FieldRecDecl, CSM,
BaseType.getCVRQualifiers(),
ConstArg && !F->isMutable()))
@@ -7782,9 +7815,9 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD,
ReturnType = Type->getReturnType();
QualType ThisType = MD->getFunctionObjectParameterType();
- QualType DeclType = Context.getTypeDeclType(RD);
- DeclType = Context.getElaboratedType(ElaboratedTypeKeyword::None, nullptr,
- DeclType, nullptr);
+ QualType DeclType =
+ Context.getTagType(ElaboratedTypeKeyword::None,
+ /*Qualifier=*/std::nullopt, RD, /*OwnsTag=*/false);
DeclType = Context.getAddrSpaceQualType(
DeclType, ThisType.getQualifiers().getAddressSpace());
QualType ExpectedReturnType = Context.getLValueReferenceType(DeclType);
@@ -7819,7 +7852,7 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD,
if (!ExplicitObjectParameter.isNull() &&
(!ExplicitObjectParameter->isReferenceType() ||
!Context.hasSameType(ExplicitObjectParameter.getNonReferenceType(),
- Context.getRecordType(RD)))) {
+ Context.getCanonicalTagType(RD)))) {
if (DeleteOnTypeMismatch)
ShouldDeleteForTypeMismatch = true;
else {
@@ -8278,7 +8311,7 @@ class DefaultedComparisonAnalyzer
Best->FoundDecl.getDecl()->isCXXClassMember()) {
QualType ObjectType = Subobj.Kind == Subobject::Member
? Args[0]->getType()
- : S.Context.getRecordType(RD);
+ : S.Context.getCanonicalTagType(RD);
if (!S.isMemberAccessibleForDeletion(
ArgClass, Best->FoundDecl, ObjectType, Subobj.Loc,
Diagnose == ExplainDeleted
@@ -8979,7 +9012,7 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD,
bool Ok = !IsMethod || FD->hasCXXExplicitFunctionObjectParameter();
QualType ExpectedTy;
if (RD)
- ExpectedTy = Context.getRecordType(RD);
+ ExpectedTy = Context.getCanonicalTagType(RD);
if (auto *Ref = CTy->getAs<LValueReferenceType>()) {
CTy = Ref->getPointeeType();
if (RD)
@@ -9002,7 +9035,7 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD,
// corresponding defaulted 'operator<=>' already.
if (!FD->isImplicit()) {
if (RD) {
- QualType PlainTy = Context.getRecordType(RD);
+ CanQualType PlainTy = Context.getCanonicalTagType(RD);
QualType RefTy =
Context.getLValueReferenceType(PlainTy.withConst());
Diag(FD->getLocation(), diag::err_defaulted_comparison_param)
@@ -9033,7 +9066,7 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD,
} else {
// Out of class, require the defaulted comparison to be a friend (of a
// complete type, per CWG2547).
- if (RequireCompleteType(FD->getLocation(), Context.getRecordType(RD),
+ if (RequireCompleteType(FD->getLocation(), Context.getCanonicalTagType(RD),
diag::err_defaulted_comparison_not_friend, int(DCK),
int(1)))
return true;
@@ -9486,15 +9519,15 @@ bool SpecialMemberDeletionInfo::isAccessible(Subobject Subobj,
CXXMethodDecl *target) {
/// If we're operating on a base class, the object type is the
/// type of this special member.
- QualType objectTy;
+ CanQualType objectTy;
AccessSpecifier access = target->getAccess();
if (CXXBaseSpecifier *base = Subobj.dyn_cast<CXXBaseSpecifier*>()) {
- objectTy = S.Context.getTypeDeclType(MD->getParent());
+ objectTy = S.Context.getCanonicalTagType(MD->getParent());
access = CXXRecordDecl::MergeAccess(base->getAccessSpecifier(), access);
// If we're operating on a field, the object type is the type of the field.
} else {
- objectTy = S.Context.getTypeDeclType(target->getParent());
+ objectTy = S.Context.getCanonicalTagType(target->getParent());
}
return S.isMemberAccessibleForDeletion(
@@ -9912,7 +9945,7 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD,
// results in an ambiguity or in a function that is deleted or inaccessible
if (CSM == CXXSpecialMemberKind::Destructor && MD->isVirtual()) {
FunctionDecl *OperatorDelete = nullptr;
- QualType DeallocType = Context.getRecordType(RD);
+ CanQualType DeallocType = Context.getCanonicalTagType(RD);
DeclarationName Name =
Context.DeclarationNames.getCXXOperatorName(OO_Delete);
ImplicitDeallocationParameters IDP = {
@@ -10245,7 +10278,7 @@ static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD,
void Sema::DiagnoseNontrivial(const CXXRecordDecl *RD,
CXXSpecialMemberKind CSM) {
- QualType Ty = Context.getRecordType(RD);
+ CanQualType Ty = Context.getCanonicalTagType(RD);
bool ConstArg = (CSM == CXXSpecialMemberKind::CopyConstructor ||
CSM == CXXSpecialMemberKind::CopyAssignment);
@@ -10293,9 +10326,9 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMemberKind CSM,
ClangABICompat14)) {
if (Diagnose)
Diag(Param0->getLocation(), diag::note_nontrivial_param_type)
- << Param0->getSourceRange() << Param0->getType()
- << Context.getLValueReferenceType(
- Context.getRecordType(RD).withConst());
+ << Param0->getSourceRange() << Param0->getType()
+ << Context.getLValueReferenceType(
+ Context.getCanonicalTagType(RD).withConst());
return false;
}
@@ -10312,8 +10345,8 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMemberKind CSM,
if (!RT || RT->getPointeeType().getCVRQualifiers()) {
if (Diagnose)
Diag(Param0->getLocation(), diag::note_nontrivial_param_type)
- << Param0->getSourceRange() << Param0->getType()
- << Context.getRValueReferenceType(Context.getRecordType(RD));
+ << Param0->getSourceRange() << Param0->getType()
+ << Context.getRValueReferenceType(Context.getCanonicalTagType(RD));
return false;
}
break;
@@ -10432,8 +10465,10 @@ struct FindHiddenVirtualMethod {
/// method overloads virtual methods in a base class without overriding any,
/// to be used with CXXRecordDecl::lookupInBases().
bool operator()(const CXXBaseSpecifier *Specifier, CXXBasePath &Path) {
- RecordDecl *BaseRecord =
- Specifier->getType()->castAs<RecordType>()->getDecl();
+ RecordDecl *BaseRecord = Specifier->getType()
+ ->castAs<RecordType>()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf();
DeclarationName Name = Method->getDeclName();
assert(Name.getNameKind() == DeclarationName::Identifier);
@@ -10591,7 +10626,8 @@ void Sema::checkIllFormedTrivialABIStruct(CXXRecordDecl &RD) {
if (const auto *RT = FT->getBaseElementTypeUnsafe()->getAs<RecordType>())
if (!RT->isDependentType() &&
- !cast<CXXRecordDecl>(RT->getDecl())->canPassInRegisters()) {
+ !cast<CXXRecordDecl>(RT->getOriginalDecl()->getDefinitionOrSelf())
+ ->canPassInRegisters()) {
PrintDiagAndRemoveAttr(5);
return;
}
@@ -10626,7 +10662,7 @@ void Sema::checkIllFormedTrivialABIStruct(CXXRecordDecl &RD) {
void Sema::checkIncorrectVTablePointerAuthenticationAttribute(
CXXRecordDecl &RD) {
- if (RequireCompleteType(RD.getLocation(), Context.getRecordType(&RD),
+ if (RequireCompleteType(RD.getLocation(), Context.getCanonicalTagType(&RD),
diag::err_incomplete_type_vtable_pointer_auth))
return;
@@ -11056,9 +11092,10 @@ void Sema::CheckConstructor(CXXConstructorDecl *Constructor) {
if (!Constructor->isInvalidDecl() &&
Constructor->hasOneParamOrDefaultArgs() &&
!Constructor->isFunctionTemplateSpecialization()) {
- QualType ParamType = Constructor->getParamDecl(0)->getType();
- QualType ClassTy = Context.getTagDeclType(ClassDecl);
- if (Context.getCanonicalType(ParamType).getUnqualifiedType() == ClassTy) {
+ CanQualType ParamType =
+ Constructor->getParamDecl(0)->getType()->getCanonicalTypeUnqualified();
+ CanQualType ClassTy = Context.getCanonicalTagType(ClassDecl);
+ if (ParamType == ClassTy) {
SourceLocation ParamLoc = Constructor->getParamDecl(0)->getLocation();
const char *ConstRef
= Constructor->getParamDecl(0)->getIdentifier() ? "const &"
@@ -11429,8 +11466,7 @@ Decl *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) {
// same object type (or a reference to it), to a (possibly
// cv-qualified) base class of that type (or a reference to it),
// or to (possibly cv-qualified) void.
- QualType ClassType
- = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl));
+ CanQualType ClassType = Context.getCanonicalTagType(ClassDecl);
if (const ReferenceType *ConvTypeRef = ConvType->getAs<ReferenceType>())
ConvType = ConvTypeRef->getPointeeType();
if (Conversion->getTemplateSpecializationKind() != TSK_Undeclared &&
@@ -11698,8 +11734,8 @@ bool Sema::CheckDeductionGuideDeclarator(Declarator &D, QualType &R,
const QualifiedTemplateName *Qualifiers =
SpecifiedName.getAsQualifiedTemplateName();
assert(Qualifiers && "expected QualifiedTemplate");
- bool SimplyWritten = !Qualifiers->hasTemplateKeyword() &&
- Qualifiers->getQualifier() == nullptr;
+ bool SimplyWritten =
+ !Qualifiers->hasTemplateKeyword() && !Qualifiers->getQualifier();
if (SimplyWritten && TemplateMatches)
AcceptableReturnType = true;
else {
@@ -11930,7 +11966,7 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
/// getNamespaceDecl - Returns the namespace a decl represents. If the decl
/// is a namespace alias, returns the namespace it points to.
-static inline NamespaceDecl *getNamespaceDecl(NamedDecl *D) {
+static inline NamespaceDecl *getNamespaceDecl(NamespaceBaseDecl *D) {
if (NamespaceAliasDecl *AD = dyn_cast_or_null<NamespaceAliasDecl>(D))
return AD->getNamespace();
return dyn_cast_or_null<NamespaceDecl>(D);
@@ -12004,10 +12040,11 @@ QualType Sema::CheckComparisonCategoryType(ComparisonCategoryType Kind,
// Use an elaborated type for diagnostics which has a name containing the
// prepended 'std' namespace but not any inline namespace names.
auto TyForDiags = [&](ComparisonCategoryInfo *Info) {
- auto *NNS =
- NestedNameSpecifier::Create(Context, nullptr, getStdNamespace());
- return Context.getElaboratedType(ElaboratedTypeKeyword::None, NNS,
- Info->getType());
+ NestedNameSpecifier Qualifier(Context, getStdNamespace(),
+ /*Prefix=*/std::nullopt);
+ return Context.getTagType(ElaboratedTypeKeyword::None, Qualifier,
+ Info->Record,
+ /*OwnsTag=*/false);
};
// Check if we've already successfully checked the comparison category type
@@ -12143,26 +12180,14 @@ static bool isStdClassTemplate(Sema &S, QualType SugaredType, QualType *TypeArg,
ClassTemplateDecl *Template = nullptr;
ArrayRef<TemplateArgument> Arguments;
- {
- const TemplateSpecializationType *TST =
- SugaredType->getAsNonAliasTemplateSpecializationType();
- if (!TST)
- if (const auto *ICN = SugaredType->getAs<InjectedClassNameType>())
- TST = ICN->getInjectedTST();
- if (TST) {
- Template = dyn_cast_or_null<ClassTemplateDecl>(
- TST->getTemplateName().getAsTemplateDecl());
- Arguments = TST->template_arguments();
- } else if (const RecordType *RT = SugaredType->getAs<RecordType>()) {
- ClassTemplateSpecializationDecl *Specialization =
- dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());
- if (!Specialization) {
- ReportMatchingNameAsMalformed(RT->getDecl());
- return false;
- }
- Template = Specialization->getSpecializedTemplate();
- Arguments = Specialization->getTemplateArgs().asArray();
- }
+ if (const TemplateSpecializationType *TST =
+ SugaredType->getAsNonAliasTemplateSpecializationType()) {
+ Template = dyn_cast_or_null<ClassTemplateDecl>(
+ TST->getTemplateName().getAsTemplateDecl());
+ Arguments = TST->template_arguments();
+ } else if (const auto *TT = SugaredType->getAs<TagType>()) {
+ Template = TT->getTemplateDecl();
+ Arguments = TT->getTemplateArgs(S.Context);
}
if (!Template) {
@@ -12288,13 +12313,8 @@ static QualType BuildStdClassTemplate(Sema &S, ClassTemplateDecl *CTD,
auto TSI = S.Context.getTrivialTypeSourceInfo(TypeParam, Loc);
Args.addArgument(TemplateArgumentLoc(TemplateArgument(TypeParam), TSI));
- QualType T = S.CheckTemplateIdType(TemplateName(CTD), Loc, Args);
- if (T.isNull())
- return QualType();
-
- return S.Context.getElaboratedType(
- ElaboratedTypeKeyword::None,
- NestedNameSpecifier::Create(S.Context, nullptr, S.getStdNamespace()), T);
+ return S.CheckTemplateIdType(ElaboratedTypeKeyword::None, TemplateName(CTD),
+ Loc, Args);
}
QualType Sema::BuildStdInitializerList(QualType Element, SourceLocation Loc) {
@@ -12436,9 +12456,7 @@ Decl *Sema::ActOnUsingDirective(Scope *S, SourceLocation UsingLoc,
S = S->getDeclParent();
UsingDirectiveDecl *UDir = nullptr;
- NestedNameSpecifier *Qualifier = nullptr;
- if (SS.isSet())
- Qualifier = SS.getScopeRep();
+ NestedNameSpecifier Qualifier = SS.getScopeRep();
// Lookup namespace name.
LookupResult R(*this, NamespcName, IdentLoc, LookupNamespaceName);
@@ -12450,14 +12468,16 @@ Decl *Sema::ActOnUsingDirective(Scope *S, SourceLocation UsingLoc,
R.clear();
// Allow "using namespace std;" or "using namespace ::std;" even if
// "std" hasn't been defined yet, for GCC compatibility.
- if ((!Qualifier || Qualifier->getKind() == NestedNameSpecifier::Global) &&
+ if ((!Qualifier ||
+ Qualifier.getKind() == NestedNameSpecifier::Kind::Global) &&
NamespcName->isStr("std")) {
Diag(IdentLoc, diag::ext_using_undefined_std);
R.addDecl(getOrCreateStdNamespace());
R.resolveKind();
}
// Otherwise, attempt typo correction.
- else TryNamespaceTypoCorrection(*this, R, S, SS, IdentLoc, NamespcName);
+ else
+ TryNamespaceTypoCorrection(*this, R, S, SS, IdentLoc, NamespcName);
}
if (!R.empty()) {
@@ -12584,7 +12604,7 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S, AccessSpecifier AS,
DiagnoseUnexpandedParameterPack(TargetNameInfo, UPPC_UsingDeclaration))
return nullptr;
} else {
- if (!SS.getScopeRep()->containsUnexpandedParameterPack() &&
+ if (!SS.getScopeRep().containsUnexpandedParameterPack() &&
!TargetNameInfo.containsUnexpandedParameterPack()) {
Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
<< SourceRange(SS.getBeginLoc(), TargetNameInfo.getEndLoc());
@@ -12869,7 +12889,7 @@ UsingShadowDecl *Sema::BuildUsingShadowDecl(Scope *S, BaseUsingDecl *BUD,
UsingDecl *Using = cast<UsingDecl>(BUD);
bool IsVirtualBase =
isVirtualDirectBase(cast<CXXRecordDecl>(CurContext),
- Using->getQualifier()->getAsRecordDecl());
+ Using->getQualifier().getAsRecordDecl());
Shadow = ConstructorUsingShadowDecl::Create(
Context, CurContext, Using->getLocation(), Using, Orig, IsVirtualBase);
} else {
@@ -12935,7 +12955,7 @@ namespace {
class UsingValidatorCCC final : public CorrectionCandidateCallback {
public:
UsingValidatorCCC(bool HasTypenameKeyword, bool IsInstantiation,
- NestedNameSpecifier *NNS, CXXRecordDecl *RequireMemberOf)
+ NestedNameSpecifier NNS, CXXRecordDecl *RequireMemberOf)
: HasTypenameKeyword(HasTypenameKeyword),
IsInstantiation(IsInstantiation), OldNNS(NNS),
RequireMemberOf(RequireMemberOf) {}
@@ -12962,24 +12982,23 @@ class UsingValidatorCCC final : public CorrectionCandidateCallback {
ASTContext &Ctx = ND->getASTContext();
if (!Ctx.getLangOpts().CPlusPlus11)
return false;
- QualType FoundType = Ctx.getRecordType(FoundRecord);
+ CanQualType FoundType = Ctx.getCanonicalTagType(FoundRecord);
// Check that the injected-class-name is named as a member of its own
// type; we don't want to suggest 'using Derived::Base;', since that
// means something else.
- NestedNameSpecifier *Specifier =
- Candidate.WillReplaceSpecifier()
- ? Candidate.getCorrectionSpecifier()
- : OldNNS;
- if (!Specifier->getAsType() ||
- !Ctx.hasSameType(QualType(Specifier->getAsType(), 0), FoundType))
+ NestedNameSpecifier Specifier = Candidate.WillReplaceSpecifier()
+ ? Candidate.getCorrectionSpecifier()
+ : OldNNS;
+ if (Specifier.getKind() != NestedNameSpecifier::Kind::Type ||
+ !Ctx.hasSameType(QualType(Specifier.getAsType(), 0), FoundType))
return false;
// Check that this inheriting constructor declaration actually names a
// direct base class of the current class.
bool AnyDependentBases = false;
if (!findDirectBaseWithType(RequireMemberOf,
- Ctx.getRecordType(FoundRecord),
+ Ctx.getCanonicalTagType(FoundRecord),
AnyDependentBases) &&
!AnyDependentBases)
return false;
@@ -13009,7 +13028,7 @@ class UsingValidatorCCC final : public CorrectionCandidateCallback {
private:
bool HasTypenameKeyword;
bool IsInstantiation;
- NestedNameSpecifier *OldNNS;
+ NestedNameSpecifier OldNNS;
CXXRecordDecl *RequireMemberOf;
};
} // end anonymous namespace
@@ -13051,7 +13070,7 @@ NamedDecl *Sema::BuildUsingDeclaration(
if (UsingName.getName().getNameKind() == DeclarationName::CXXConstructorName)
if (auto *RD = dyn_cast<CXXRecordDecl>(CurContext))
UsingName.setName(Context.DeclarationNames.getCXXConstructorName(
- Context.getCanonicalType(Context.getRecordType(RD))));
+ Context.getCanonicalTagType(RD)));
// Do the redeclaration lookup in the current scope.
LookupResult Previous(*this, UsingName, LookupUsingDeclName,
@@ -13154,7 +13173,7 @@ NamedDecl *Sema::BuildUsingDeclaration(
// equal to that of the current context.
if (CurContext->isRecord()) {
R.setBaseObjectType(
- Context.getTypeDeclType(cast<CXXRecordDecl>(CurContext)));
+ Context.getCanonicalTagType(cast<CXXRecordDecl>(CurContext)));
}
LookupQualifiedName(R, LookupContext);
@@ -13220,7 +13239,7 @@ NamedDecl *Sema::BuildUsingDeclaration(
// constructor.
auto *CurClass = cast<CXXRecordDecl>(CurContext);
UsingName.setName(Context.DeclarationNames.getCXXConstructorName(
- Context.getCanonicalType(Context.getRecordType(CurClass))));
+ Context.getCanonicalTagType(CurClass)));
UsingName.setNamedTypeInfo(nullptr);
for (auto *Ctor : LookupConstructors(RD))
R.addDecl(Ctor);
@@ -13366,20 +13385,16 @@ NamedDecl *Sema::BuildUsingPackDecl(NamedDecl *InstantiatedFrom,
bool Sema::CheckInheritingConstructorUsingDecl(UsingDecl *UD) {
assert(!UD->hasTypename() && "expecting a constructor name");
- const Type *SourceType = UD->getQualifier()->getAsType();
- assert(SourceType &&
- "Using decl naming constructor doesn't have type in scope spec.");
+ QualType SourceType(UD->getQualifier().getAsType(), 0);
CXXRecordDecl *TargetClass = cast<CXXRecordDecl>(CurContext);
// Check whether the named type is a direct base class.
bool AnyDependentBases = false;
- auto *Base = findDirectBaseWithType(TargetClass, QualType(SourceType, 0),
- AnyDependentBases);
+ auto *Base =
+ findDirectBaseWithType(TargetClass, SourceType, AnyDependentBases);
if (!Base && !AnyDependentBases) {
- Diag(UD->getUsingLoc(),
- diag::err_using_decl_constructor_not_in_direct_base)
- << UD->getNameInfo().getSourceRange()
- << QualType(SourceType, 0) << TargetClass;
+ Diag(UD->getUsingLoc(), diag::err_using_decl_constructor_not_in_direct_base)
+ << UD->getNameInfo().getSourceRange() << SourceType << TargetClass;
UD->setInvalidDecl();
return true;
}
@@ -13395,7 +13410,7 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
const CXXScopeSpec &SS,
SourceLocation NameLoc,
const LookupResult &Prev) {
- NestedNameSpecifier *Qual = SS.getScopeRep();
+ NestedNameSpecifier Qual = SS.getScopeRep();
// C++03 [namespace.udecl]p8:
// C++0x [namespace.udecl]p10:
@@ -13410,7 +13425,7 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
// declaration in the same scope.
// FIXME: How should we check for dependent type-type conflicts at block
// scope?
- if (Qual->isDependent() && !HasTypenameKeyword) {
+ if (Qual.isDependent() && !HasTypenameKeyword) {
for (auto *D : Prev) {
if (!isa<TypeDecl>(D) && !isa<UsingDecl>(D) && !isa<UsingPackDecl>(D)) {
bool OldCouldBeEnumerator =
@@ -13427,13 +13442,12 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
return false;
}
- const NestedNameSpecifier *CNNS =
- Context.getCanonicalNestedNameSpecifier(Qual);
+ NestedNameSpecifier CNNS = Qual.getCanonical();
for (LookupResult::iterator I = Prev.begin(), E = Prev.end(); I != E; ++I) {
NamedDecl *D = *I;
bool DTypename;
- NestedNameSpecifier *DQual;
+ NestedNameSpecifier DQual = std::nullopt;
if (UsingDecl *UD = dyn_cast<UsingDecl>(D)) {
DTypename = UD->hasTypename();
DQual = UD->getQualifier();
@@ -13454,7 +13468,7 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
// using decls differ if they name different scopes (but note that
// template instantiation can cause this check to trigger when it
// didn't before instantiation).
- if (CNNS != Context.getCanonicalNestedNameSpecifier(DQual))
+ if (CNNS != DQual.getCanonical())
continue;
Diag(NameLoc, diag::err_using_decl_redeclaration) << SS.getRange();
@@ -13829,7 +13843,7 @@ Decl *Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation NamespaceLoc,
}
}
assert(!R.isAmbiguous() && !R.empty());
- NamedDecl *ND = R.getRepresentativeDecl();
+ auto *ND = cast<NamespaceBaseDecl>(R.getRepresentativeDecl());
// Check if we have a previous declaration with the same name.
LookupResult PrevR(*this, Alias, AliasLoc, LookupOrdinaryName,
@@ -13914,7 +13928,8 @@ bool SpecialMemberExceptionSpecInfo::visitBase(CXXBaseSpecifier *Base) {
if (!RT)
return false;
- auto *BaseClass = cast<CXXRecordDecl>(RT->getDecl());
+ auto *BaseClass =
+ cast<CXXRecordDecl>(RT->getOriginalDecl())->getDefinitionOrSelf();
Sema::SpecialMemberOverloadResult SMOR = lookupInheritedCtor(BaseClass);
if (auto *BaseCtor = SMOR.getMethod()) {
visitSubobjectCall(Base, BaseCtor);
@@ -13940,8 +13955,9 @@ bool SpecialMemberExceptionSpecInfo::visitField(FieldDecl *FD) {
ExceptSpec.CalledExpr(E);
} else if (auto *RT = S.Context.getBaseElementType(FD->getType())
->getAs<RecordType>()) {
- visitClassSubobject(cast<CXXRecordDecl>(RT->getDecl()), FD,
- FD->getType().getCVRQualifiers());
+ visitClassSubobject(
+ cast<CXXRecordDecl>(RT->getOriginalDecl())->getDefinitionOrSelf(), FD,
+ FD->getType().getCVRQualifiers());
}
return false;
}
@@ -14003,7 +14019,7 @@ ComputeDefaultedSpecialMemberExceptionSpec(
// attempting to resolve an exception specification before it's known
// at a higher level.
if (S.RequireCompleteType(MD->getLocation(),
- S.Context.getRecordType(ClassDecl),
+ S.Context.getCanonicalTagType(ClassDecl),
diag::err_exception_spec_incomplete_type))
return Info.ExceptSpec;
@@ -14134,8 +14150,7 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(
*this, ClassDecl, CXXSpecialMemberKind::DefaultConstructor, false);
// Create the actual constructor declaration.
- CanQualType ClassType
- = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl));
+ CanQualType ClassType = Context.getCanonicalTagType(ClassDecl);
SourceLocation ClassLoc = ClassDecl->getLocation();
DeclarationName Name
= Context.DeclarationNames.getCXXConstructorName(ClassType);
@@ -14420,8 +14435,7 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) {
*this, ClassDecl, CXXSpecialMemberKind::Destructor, false);
// Create the actual destructor declaration.
- CanQualType ClassType
- = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl));
+ CanQualType ClassType = Context.getCanonicalTagType(ClassDecl);
SourceLocation ClassLoc = ClassDecl->getLocation();
DeclarationName Name
= Context.DeclarationNames.getCXXDestructorName(ClassType);
@@ -14759,9 +14773,10 @@ buildMemcpyForAssignmentOp(Sema &S, SourceLocation Loc, QualType T,
VK_PRValue, OK_Ordinary, Loc, false, S.CurFPFeatureOverrides());
const Type *E = T->getBaseElementTypeUnsafe();
- bool NeedsCollectableMemCpy =
- E->isRecordType() &&
- E->castAs<RecordType>()->getDecl()->hasObjectMember();
+ bool NeedsCollectableMemCpy = E->isRecordType() && E->castAs<RecordType>()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->hasObjectMember();
// Create a reference to the __builtin_objc_memmove_collectable function
StringRef MemCpyName = NeedsCollectableMemCpy ?
@@ -14838,7 +14853,8 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T,
// ignoring any possible virtual overriding functions in more derived
// classes);
if (const RecordType *RecordTy = T->getAs<RecordType>()) {
- CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(RecordTy->getDecl());
+ CXXRecordDecl *ClassDecl =
+ cast<CXXRecordDecl>(RecordTy->getOriginalDecl())->getDefinitionOrSelf();
// Look for operator=.
DeclarationName Name
@@ -14885,10 +14901,9 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T,
// reference to operator=; this is required to suppress the virtual
// call mechanism.
CXXScopeSpec SS;
+ // FIXME: Don't canonicalize this.
const Type *CanonicalT = S.Context.getCanonicalType(T.getTypePtr());
- SS.MakeTrivial(S.Context,
- NestedNameSpecifier::Create(S.Context, nullptr, CanonicalT),
- Loc);
+ SS.MakeTrivial(S.Context, NestedNameSpecifier(CanonicalT), Loc);
// Create the reference to operator=.
ExprResult OpEqualRef
@@ -15042,9 +15057,9 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {
if (DSM.isAlreadyBeingDeclared())
return nullptr;
- QualType ArgType = Context.getTypeDeclType(ClassDecl);
- ArgType = Context.getElaboratedType(ElaboratedTypeKeyword::None, nullptr,
- ArgType, nullptr);
+ QualType ArgType = Context.getTagType(ElaboratedTypeKeyword::None,
+ /*Qualifier=*/std::nullopt, ClassDecl,
+ /*OwnsTag=*/false);
LangAS AS = getDefaultCXXMethodAddrSpace();
if (AS != LangAS::Default)
ArgType = Context.getAddrSpaceQualType(ArgType, AS);
@@ -15303,7 +15318,8 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
// Check for members of reference type; we can't copy those.
if (Field->getType()->isReferenceType()) {
Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign)
- << Context.getTagDeclType(ClassDecl) << 0 << Field->getDeclName();
+ << Context.getCanonicalTagType(ClassDecl) << 0
+ << Field->getDeclName();
Diag(Field->getLocation(), diag::note_declared_at);
Invalid = true;
continue;
@@ -15313,7 +15329,8 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
QualType BaseType = Context.getBaseElementType(Field->getType());
if (!BaseType->getAs<RecordType>() && BaseType.isConstQualified()) {
Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign)
- << Context.getTagDeclType(ClassDecl) << 1 << Field->getDeclName();
+ << Context.getCanonicalTagType(ClassDecl) << 1
+ << Field->getDeclName();
Diag(Field->getLocation(), diag::note_declared_at);
Invalid = true;
continue;
@@ -15398,9 +15415,9 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) {
// Note: The following rules are largely analoguous to the move
// constructor rules.
- QualType ArgType = Context.getTypeDeclType(ClassDecl);
- ArgType = Context.getElaboratedType(ElaboratedTypeKeyword::None, nullptr,
- ArgType, nullptr);
+ QualType ArgType = Context.getTagType(ElaboratedTypeKeyword::None,
+ /*Qualifier=*/std::nullopt, ClassDecl,
+ /*OwnsTag=*/false);
LangAS AS = getDefaultCXXMethodAddrSpace();
if (AS != LangAS::Default)
ArgType = Context.getAddrSpaceQualType(ArgType, AS);
@@ -15690,7 +15707,8 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
// Check for members of reference type; we can't move those.
if (Field->getType()->isReferenceType()) {
Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign)
- << Context.getTagDeclType(ClassDecl) << 0 << Field->getDeclName();
+ << Context.getCanonicalTagType(ClassDecl) << 0
+ << Field->getDeclName();
Diag(Field->getLocation(), diag::note_declared_at);
Invalid = true;
continue;
@@ -15700,7 +15718,8 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
QualType BaseType = Context.getBaseElementType(Field->getType());
if (!BaseType->getAs<RecordType>() && BaseType.isConstQualified()) {
Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign)
- << Context.getTagDeclType(ClassDecl) << 1 << Field->getDeclName();
+ << Context.getCanonicalTagType(ClassDecl) << 1
+ << Field->getDeclName();
Diag(Field->getLocation(), diag::note_declared_at);
Invalid = true;
continue;
@@ -15791,10 +15810,10 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
if (DSM.isAlreadyBeingDeclared())
return nullptr;
- QualType ClassType = Context.getTypeDeclType(ClassDecl);
+ QualType ClassType = Context.getTagType(ElaboratedTypeKeyword::None,
+ /*Qualifier=*/std::nullopt, ClassDecl,
+ /*OwnsTag=*/false);
QualType ArgType = ClassType;
- ArgType = Context.getElaboratedType(ElaboratedTypeKeyword::None, nullptr,
- ArgType, nullptr);
bool Const = ClassDecl->implicitCopyConstructorHasConstParam();
if (Const)
ArgType = ArgType.withConst();
@@ -15938,11 +15957,11 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor(
if (DSM.isAlreadyBeingDeclared())
return nullptr;
- QualType ClassType = Context.getTypeDeclType(ClassDecl);
+ QualType ClassType = Context.getTagType(ElaboratedTypeKeyword::None,
+ /*Qualifier=*/std::nullopt, ClassDecl,
+ /*OwnsTag=*/false);
QualType ArgType = ClassType;
- ArgType = Context.getElaboratedType(ElaboratedTypeKeyword::None, nullptr,
- ArgType, nullptr);
LangAS AS = getDefaultCXXMethodAddrSpace();
if (AS != LangAS::Default)
ArgType = Context.getAddrSpaceQualType(ClassType, AS);
@@ -16297,7 +16316,8 @@ void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) {
if (VD->getInit() && VD->getInit()->containsErrors())
return;
- CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Record->getDecl());
+ CXXRecordDecl *ClassDecl =
+ cast<CXXRecordDecl>(Record->getOriginalDecl())->getDefinitionOrSelf();
if (ClassDecl->isInvalidDecl()) return;
if (ClassDecl->hasIrrelevantDestructor()) return;
if (ClassDecl->isDependentContext()) return;
@@ -16643,10 +16663,10 @@ static inline bool CheckOperatorNewDeleteTypes(
if (CheckType(SizeParameterIndex, SemaRef.Context.getSizeType(), "size_t"))
return true;
- TypeDecl *StdAlignValTDecl = SemaRef.getStdAlignValT();
- QualType StdAlignValT =
- StdAlignValTDecl ? SemaRef.Context.getTypeDeclType(StdAlignValTDecl)
- : QualType();
+ TagDecl *StdAlignValTDecl = SemaRef.getStdAlignValT();
+ CanQualType StdAlignValT =
+ StdAlignValTDecl ? SemaRef.Context.getCanonicalTagType(StdAlignValTDecl)
+ : CanQualType();
if (CheckType(SizeParameterIndex + 1, StdAlignValT, "std::align_val_t"))
return true;
@@ -16686,8 +16706,8 @@ CheckOperatorDeleteDeclaration(Sema &SemaRef, FunctionDecl *FnDecl) {
auto *MD = dyn_cast<CXXMethodDecl>(FnDecl);
auto ConstructDestroyingDeleteAddressType = [&]() {
assert(MD);
- return SemaRef.Context.getCanonicalType(SemaRef.Context.getPointerType(
- SemaRef.Context.getRecordType(MD->getParent())));
+ return SemaRef.Context.getPointerType(
+ SemaRef.Context.getCanonicalTagType(MD->getParent()));
};
// C++ P2719: A destroying operator delete cannot be type aware
@@ -16726,8 +16746,8 @@ CheckOperatorDeleteDeclaration(Sema &SemaRef, FunctionDecl *FnDecl) {
// function shall be of type void *.
CanQualType ExpectedAddressParamType =
MD && IsPotentiallyDestroyingOperatorDelete(SemaRef, MD)
- ? SemaRef.Context.getCanonicalType(SemaRef.Context.getPointerType(
- SemaRef.Context.getRecordType(MD->getParent())))
+ ? SemaRef.Context.getPointerType(
+ SemaRef.Context.getCanonicalTagType(MD->getParent()))
: SemaRef.Context.VoidPtrTy;
// C++ [basic.stc.dynamic.deallocation]p2:
@@ -17958,27 +17978,14 @@ DeclResult Sema::ActOnTemplatedFriendTag(
/*OOK=*/OffsetOfKind::Outside);
}
+ TypeSourceInfo *TSI = nullptr;
ElaboratedTypeKeyword Keyword
= TypeWithKeyword::getKeywordForTagTypeKind(Kind);
- QualType T = CheckTypenameType(Keyword, TagLoc, QualifierLoc,
- *Name, NameLoc);
+ QualType T = CheckTypenameType(Keyword, TagLoc, QualifierLoc, *Name,
+ NameLoc, &TSI, /*DeducedTSTContext=*/true);
if (T.isNull())
return true;
- TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T);
- if (isa<DependentNameType>(T)) {
- DependentNameTypeLoc TL =
- TSI->getTypeLoc().castAs<DependentNameTypeLoc>();
- TL.setElaboratedKeywordLoc(TagLoc);
- TL.setQualifierLoc(QualifierLoc);
- TL.setNameLoc(NameLoc);
- } else {
- ElaboratedTypeLoc TL = TSI->getTypeLoc().castAs<ElaboratedTypeLoc>();
- TL.setElaboratedKeywordLoc(TagLoc);
- TL.setQualifierLoc(QualifierLoc);
- TL.getNamedTypeLoc().castAs<TypeSpecTypeLoc>().setNameLoc(NameLoc);
- }
-
FriendDecl *Friend =
FriendDecl::Create(Context, CurContext, NameLoc, TSI, FriendLoc,
EllipsisLoc, TempParamLists);
@@ -18290,7 +18297,7 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
// - There's a non-dependent scope specifier, in which case we
// compute it and do a previous lookup there for a function
// or function template.
- } else if (!SS.getScopeRep()->isDependent()) {
+ } else if (!SS.getScopeRep().isDependent()) {
DC = computeDeclContext(SS);
if (!DC) return nullptr;
@@ -18789,7 +18796,7 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
// complete at the point of declaration of D::f or shall be the class
// type D.
if (const RecordType *RT = NewClassTy->getAs<RecordType>()) {
- if (!RT->isBeingDefined() &&
+ if (!RT->getOriginalDecl()->isEntityBeingDefined() &&
RequireCompleteType(New->getLocation(), NewClassTy,
diag::err_covariant_return_incomplete,
New->getDeclName()))
@@ -19166,8 +19173,9 @@ void Sema::MarkVirtualMembersReferenced(SourceLocation Loc,
return;
for (const auto &I : RD->bases()) {
- const auto *Base =
- cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl());
+ const auto *Base = cast<CXXRecordDecl>(
+ I.getType()->castAs<RecordType>()->getOriginalDecl())
+ ->getDefinitionOrSelf();
if (Base->getNumVBases() == 0)
continue;
MarkVirtualMembersReferenced(Loc, Base);
diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp
index 9dbc3efbca405..4614cf766b19c 100644
--- a/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/clang/lib/Sema/SemaDeclObjC.cpp
@@ -591,12 +591,13 @@ void SemaObjC::ActOnSuperClassOfClassInterface(
// The previous declaration was not a class decl. Check if we have a
// typedef. If we do, get the underlying class type.
if (const TypedefNameDecl *TDecl =
- dyn_cast_or_null<TypedefNameDecl>(PrevDecl)) {
+ dyn_cast_or_null<TypedefNameDecl>(PrevDecl)) {
QualType T = TDecl->getUnderlyingType();
if (T->isObjCObjectType()) {
if (NamedDecl *IDecl = T->castAs<ObjCObjectType>()->getInterface()) {
SuperClassDecl = dyn_cast<ObjCInterfaceDecl>(IDecl);
- SuperClassType = Context.getTypeDeclType(TDecl);
+ SuperClassType = Context.getTypeDeclType(
+ ElaboratedTypeKeyword::None, /*Qualifier=*/std::nullopt, TDecl);
// This handles the following case:
// @interface NewI @end
@@ -1389,11 +1390,9 @@ class ObjCTypeArgOrProtocolValidatorCCC final
// Make sure the type is something we would accept as a type
// argument.
- auto type = Context.getTypeDeclType(typeDecl);
- if (type->isObjCObjectPointerType() ||
- type->isBlockPointerType() ||
+ if (CanQualType type = Context.getCanonicalTypeDeclType(typeDecl);
type->isDependentType() ||
- type->isObjCObjectType())
+ isa<ObjCObjectPointerType, BlockPointerType, ObjCObjectType>(type))
return true;
return false;
@@ -1589,7 +1588,9 @@ void SemaObjC::actOnObjCTypeArgsOrProtocolQualifiers(
unsigned diagID; // unused
QualType type;
if (auto *actualTypeDecl = dyn_cast<TypeDecl *>(typeDecl))
- type = Context.getTypeDeclType(actualTypeDecl);
+ type =
+ Context.getTypeDeclType(ElaboratedTypeKeyword::None,
+ /*Qualifier=*/std::nullopt, actualTypeDecl);
else
type = Context.getObjCInterfaceType(cast<ObjCInterfaceDecl *>(typeDecl));
TypeSourceInfo *parsedTSInfo = Context.getTrivialTypeSourceInfo(type, loc);
@@ -3231,8 +3232,10 @@ static bool tryMatchRecordTypes(ASTContext &Context,
assert(lt && rt && lt != rt);
if (!isa<RecordType>(lt) || !isa<RecordType>(rt)) return false;
- RecordDecl *left = cast<RecordType>(lt)->getDecl();
- RecordDecl *right = cast<RecordType>(rt)->getDecl();
+ RecordDecl *left =
+ cast<RecordType>(lt)->getOriginalDecl()->getDefinitionOrSelf();
+ RecordDecl *right =
+ cast<RecordType>(rt)->getOriginalDecl()->getDefinitionOrSelf();
// Require union-hood to match.
if (left->isUnion() != right->isUnion()) return false;
@@ -3846,7 +3849,9 @@ static bool IsVariableSizedType(QualType T) {
if (T->isIncompleteArrayType())
return true;
const auto *RecordTy = T->getAs<RecordType>();
- return (RecordTy && RecordTy->getDecl()->hasFlexibleArrayMember());
+ return (RecordTy && RecordTy->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->hasFlexibleArrayMember());
}
static void DiagnoseVariableSizedIvars(Sema &S, ObjCContainerDecl *OCD) {
@@ -3892,7 +3897,9 @@ static void DiagnoseVariableSizedIvars(Sema &S, ObjCContainerDecl *OCD) {
<< TagTypeKind::Class; // Use "class" for Obj-C.
IsInvalidIvar = true;
} else if (const RecordType *RecordTy = IvarTy->getAs<RecordType>()) {
- if (RecordTy->getDecl()->hasFlexibleArrayMember()) {
+ if (RecordTy->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->hasFlexibleArrayMember()) {
S.Diag(ivar->getLocation(),
diag::err_objc_variable_sized_type_not_at_end)
<< ivar->getDeclName() << IvarTy;
@@ -5537,7 +5544,8 @@ void SemaObjC::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) {
if (const RecordType *RecordTy =
Context.getBaseElementType(Field->getType())
->getAs<RecordType>()) {
- CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getOriginalDecl())
+ ->getDefinitionOrSelf();
if (CXXDestructorDecl *Destructor = SemaRef.LookupDestructor(RD)) {
SemaRef.MarkFunctionReferenced(Field->getLocation(), Destructor);
SemaRef.CheckDestructorAccess(
diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp
index 0a6cea8869c14..94413b5b92d22 100644
--- a/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -163,8 +163,9 @@ bool Sema::CheckSpecifiedExceptionType(QualType &T, SourceRange Range) {
DiagID = diag::ext_incomplete_in_exception_spec;
ReturnValueOnError = false;
}
- if (!(PointeeT->isRecordType() &&
- PointeeT->castAs<RecordType>()->isBeingDefined()) &&
+ if (!(PointeeT->isRecordType() && PointeeT->castAs<RecordType>()
+ ->getOriginalDecl()
+ ->isEntityBeingDefined()) &&
RequireCompleteType(Range.getBegin(), PointeeT, DiagID, Kind, Range))
return ReturnValueOnError;
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 3c3d29c415249..fbab232f65701 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -1527,8 +1527,8 @@ void Sema::checkEnumArithmeticConversions(Expr *LHS, Expr *RHS,
// are ill-formed.
if (getLangOpts().CPlusPlus26)
DiagID = diag::warn_conv_mixed_enum_types_cxx26;
- else if (!L->castAs<EnumType>()->getDecl()->hasNameForLinkage() ||
- !R->castAs<EnumType>()->getDecl()->hasNameForLinkage()) {
+ else if (!L->castAs<EnumType>()->getOriginalDecl()->hasNameForLinkage() ||
+ !R->castAs<EnumType>()->getOriginalDecl()->hasNameForLinkage()) {
// If either enumeration type is unnamed, it's less likely that the
// user cares about this, but this situation is still deprecated in
// C++2a. Use a different warning group.
@@ -2529,7 +2529,7 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
if (isa<CXXRecordDecl>(DC)) {
if (ExplicitTemplateArgs) {
if (LookupTemplateName(
- R, S, SS, Context.getRecordType(cast<CXXRecordDecl>(DC)),
+ R, S, SS, Context.getCanonicalTagType(cast<CXXRecordDecl>(DC)),
/*EnteringContext*/ false, TemplateNameIsRequired,
/*RequiredTemplateKind*/ nullptr, /*AllowTypoCorrection*/ true))
return true;
@@ -2605,11 +2605,8 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
}
R.addDecl(ND);
if (getLangOpts().CPlusPlus && ND->isCXXClassMember()) {
- CXXRecordDecl *Record = nullptr;
- if (Corrected.getCorrectionSpecifier()) {
- const Type *Ty = Corrected.getCorrectionSpecifier()->getAsType();
- Record = Ty->getAsCXXRecordDecl();
- }
+ CXXRecordDecl *Record =
+ Corrected.getCorrectionSpecifier().getAsRecordDecl();
if (!Record)
Record = cast<CXXRecordDecl>(
ND->getDeclContext()->getRedeclContext());
@@ -2705,8 +2702,7 @@ recoverFromMSUnqualifiedLookup(Sema &S, ASTContext &Context,
// Synthesize a fake NNS that points to the derived class. This will
// perform name lookup during template instantiation.
CXXScopeSpec SS;
- auto *NNS =
- NestedNameSpecifier::Create(Context, nullptr, RD->getTypeForDecl());
+ NestedNameSpecifier NNS(Context.getCanonicalTagType(RD)->getTypePtr());
SS.MakeTrivial(Context, NNS, SourceRange(Loc, Loc));
return DependentScopeDeclRefExpr::Create(
Context, SS.getWithLocInContext(Context), TemplateKWLoc, NameInfo,
@@ -2829,8 +2825,7 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
// If this name wasn't predeclared and if this is not a function
// call, diagnose the problem.
- DefaultFilterCCC DefaultValidator(II, SS.isValid() ? SS.getScopeRep()
- : nullptr);
+ DefaultFilterCCC DefaultValidator(II, SS.getScopeRep());
DefaultValidator.IsAddressOfOperand = IsAddressOfOperand;
assert((!CCC || CCC->IsAddressOfOperand == IsAddressOfOperand) &&
"Typo correction callback misconfigured");
@@ -2940,8 +2935,28 @@ ExprResult Sema::BuildQualifiedDeclarationNameExpr(
}
if (const TypeDecl *TD = R.getAsSingle<TypeDecl>()) {
- QualType Ty = Context.getTypeDeclType(TD);
- QualType ET = getElaboratedType(ElaboratedTypeKeyword::None, SS, Ty);
+ QualType ET;
+ TypeLocBuilder TLB;
+ if (auto *TagD = dyn_cast<TagDecl>(TD)) {
+ ET = SemaRef.Context.getTagType(ElaboratedTypeKeyword::None,
+ SS.getScopeRep(), TagD,
+ /*OwnsTag=*/false);
+ auto TL = TLB.push<TagTypeLoc>(ET);
+ TL.setElaboratedKeywordLoc(SourceLocation());
+ TL.setQualifierLoc(SS.getWithLocInContext(Context));
+ TL.setNameLoc(NameInfo.getLoc());
+ } else if (auto *TypedefD = dyn_cast<TypedefNameDecl>(TD)) {
+ ET = SemaRef.Context.getTypedefType(ElaboratedTypeKeyword::None,
+ SS.getScopeRep(), TypedefD);
+ TLB.push<TypedefTypeLoc>(ET).set(
+ /*ElaboratedKeywordLoc=*/SourceLocation(),
+ SS.getWithLocInContext(Context), NameInfo.getLoc());
+ } else {
+ // FIXME: What else can appear here?
+ ET = SemaRef.Context.getTypeDeclType(TD);
+ TLB.pushTypeSpec(ET).setNameLoc(NameInfo.getLoc());
+ assert(SS.isEmpty());
+ }
// Diagnose a missing typename if this resolved unambiguously to a type in
// a dependent context. If we can recover with a type, downgrade this to
@@ -2962,13 +2977,6 @@ ExprResult Sema::BuildQualifiedDeclarationNameExpr(
D << FixItHint::CreateInsertion(Loc, "typename ");
// Recover by pretending this was an elaborated type.
- TypeLocBuilder TLB;
- TLB.pushTypeSpec(Ty).setNameLoc(NameInfo.getLoc());
-
- ElaboratedTypeLoc QTL = TLB.push<ElaboratedTypeLoc>(ET);
- QTL.setElaboratedKeywordLoc(SourceLocation());
- QTL.setQualifierLoc(SS.getWithLocInContext(Context));
-
*RecoveryTSI = TLB.getTypeSourceInfo(Context, ET);
return ExprEmpty();
@@ -2984,11 +2992,10 @@ ExprResult Sema::BuildQualifiedDeclarationNameExpr(
return BuildDeclarationNameExpr(SS, R, /*ADL=*/false);
}
-ExprResult
-Sema::PerformObjectMemberConversion(Expr *From,
- NestedNameSpecifier *Qualifier,
- NamedDecl *FoundDecl,
- NamedDecl *Member) {
+ExprResult Sema::PerformObjectMemberConversion(Expr *From,
+ NestedNameSpecifier Qualifier,
+ NamedDecl *FoundDecl,
+ NamedDecl *Member) {
const auto *RD = dyn_cast<CXXRecordDecl>(Member->getDeclContext());
if (!RD)
return From;
@@ -2999,7 +3006,7 @@ Sema::PerformObjectMemberConversion(Expr *From,
QualType FromType = From->getType();
bool PointerConversions = false;
if (isa<FieldDecl>(Member)) {
- DestRecordType = Context.getCanonicalType(Context.getTypeDeclType(RD));
+ DestRecordType = Context.getCanonicalTagType(RD);
auto FromPtrType = FromType->getAs<PointerType>();
DestRecordType = Context.getAddrSpaceQualType(
DestRecordType, FromPtrType
@@ -3077,8 +3084,8 @@ Sema::PerformObjectMemberConversion(Expr *From,
// x = 17; // error: ambiguous base subobjects
// Derived1::x = 17; // okay, pick the Base subobject of Derived1
// }
- if (Qualifier && Qualifier->getAsType()) {
- QualType QType = QualType(Qualifier->getAsType(), 0);
+ if (Qualifier.getKind() == NestedNameSpecifier::Kind::Type) {
+ QualType QType = QualType(Qualifier.getAsType(), 0);
assert(QType->isRecordType() && "lookup done with non-record type");
QualType QRecordType = QualType(QType->castAs<RecordType>(), 0);
@@ -4480,9 +4487,6 @@ static void captureVariablyModifiedType(ASTContext &Context, QualType T,
case Type::BitInt:
case Type::HLSLInlineSpirv:
llvm_unreachable("type class is never variably-modified!");
- case Type::Elaborated:
- T = cast<ElaboratedType>(Ty)->getNamedType();
- break;
case Type::Adjusted:
T = cast<AdjustedType>(Ty)->getOriginalType();
break;
@@ -5871,7 +5875,7 @@ static bool isParenthetizedAndQualifiedAddressOfExpr(Expr *Fn) {
return DRE->hasQualifier();
}
if (auto *OVL = dyn_cast<OverloadExpr>(UO->getSubExpr()->IgnoreParens()))
- return OVL->getQualifier();
+ return bool(OVL->getQualifier());
return false;
}
@@ -7071,7 +7075,7 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
for (unsigned i = 0, e = Args.size(); i != e; i++) {
if (const auto *RT =
dyn_cast<RecordType>(Args[i]->getType().getCanonicalType())) {
- if (RT->getDecl()->isOrContainsUnion())
+ if (RT->getOriginalDecl()->isOrContainsUnion())
Diag(Args[i]->getBeginLoc(), diag::warn_cmse_nonsecure_union)
<< 0 << i;
}
@@ -8600,7 +8604,8 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
// type.
if (const RecordType *LHSRT = LHSTy->getAs<RecordType>()) { // C99 6.5.15p3
if (const RecordType *RHSRT = RHSTy->getAs<RecordType>())
- if (LHSRT->getDecl() == RHSRT->getDecl())
+ if (declaresSameEntity(LHSRT->getOriginalDecl(),
+ RHSRT->getOriginalDecl()))
// "If both the operands have structure or union type, the result has
// that type." This implies that CV qualifiers are dropped.
return Context.getCommonSugaredType(LHSTy.getUnqualifiedType(),
@@ -9669,11 +9674,14 @@ Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType,
// If the ArgType is a Union type, we want to handle a potential
// transparent_union GCC extension.
const RecordType *UT = ArgType->getAsUnionType();
- if (!UT || !UT->getDecl()->hasAttr<TransparentUnionAttr>())
+ if (!UT)
+ return AssignConvertType::Incompatible;
+
+ RecordDecl *UD = UT->getOriginalDecl()->getDefinitionOrSelf();
+ if (!UD->hasAttr<TransparentUnionAttr>())
return AssignConvertType::Incompatible;
// The field to initialize within the transparent union.
- RecordDecl *UD = UT->getDecl();
FieldDecl *InitField = nullptr;
// It's compatible if the expression matches any of the fields.
for (auto *it : UD->fields()) {
@@ -11396,7 +11404,7 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS,
static bool isScopedEnumerationType(QualType T) {
if (const EnumType *ET = T->getAs<EnumType>())
- return ET->getDecl()->isScoped();
+ return ET->getOriginalDecl()->isScoped();
return false;
}
@@ -12285,8 +12293,10 @@ static QualType checkArithmeticOrEnumeralThreeWayCompare(Sema &S,
S.InvalidOperands(Loc, LHS, RHS);
return QualType();
}
- QualType IntType =
- LHSStrippedType->castAs<EnumType>()->getDecl()->getIntegerType();
+ QualType IntType = LHSStrippedType->castAs<EnumType>()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->getIntegerType();
assert(IntType->isArithmeticType());
// We can't use `CK_IntegralCast` when the underlying type is 'bool', so we
@@ -12452,7 +12462,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
auto computeResultTy = [&]() {
if (Opc != BO_Cmp)
- return Context.getLogicalOperationType();
+ return QualType(Context.getLogicalOperationType());
assert(getLangOpts().CPlusPlus);
assert(Context.hasSameType(LHS.get()->getType(), RHS.get()->getType()));
@@ -13689,8 +13699,10 @@ static void DiagnoseRecursiveConstFields(Sema &S, const ValueDecl *VD,
// diagnostics in field nesting order.
while (RecordTypeList.size() > NextToCheckIndex) {
bool IsNested = NextToCheckIndex > 0;
- for (const FieldDecl *Field :
- RecordTypeList[NextToCheckIndex]->getDecl()->fields()) {
+ for (const FieldDecl *Field : RecordTypeList[NextToCheckIndex]
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->fields()) {
// First, check every field for constness.
QualType FieldTy = Field->getType();
if (FieldTy.isConstQualified()) {
@@ -16145,7 +16157,7 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
if (!RC)
return ExprError(Diag(OC.LocEnd, diag::err_offsetof_record_type)
<< CurrentType);
- RecordDecl *RD = RC->getDecl();
+ RecordDecl *RD = RC->getOriginalDecl()->getDefinitionOrSelf();
// C++ [lib.support.types]p5:
// The macro offsetof accepts a restricted set of type arguments in this
@@ -16206,8 +16218,8 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
// If the member was found in a base class, introduce OffsetOfNodes for
// the base class indirections.
CXXBasePaths Paths;
- if (IsDerivedFrom(OC.LocStart, CurrentType, Context.getTypeDeclType(Parent),
- Paths)) {
+ if (IsDerivedFrom(OC.LocStart, CurrentType,
+ Context.getCanonicalTagType(Parent), Paths)) {
if (Paths.getDetectedVirtual()) {
Diag(OC.LocEnd, diag::err_offsetof_field_of_virtual_base)
<< MemberDecl->getDeclName()
@@ -16772,7 +16784,8 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc,
// that.
QualType UnderlyingType = TInfo->getType();
if (const auto *ET = UnderlyingType->getAs<EnumType>())
- UnderlyingType = ET->getDecl()->getIntegerType();
+ UnderlyingType =
+ ET->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
if (Context.typesAreCompatible(PromoteType, UnderlyingType,
/*CompareUnqualified*/ true))
PromoteType = QualType();
@@ -16918,7 +16931,7 @@ ExprResult Sema::ActOnSourceLocExpr(SourceLocIdentKind Kind,
return ExprError();
}
ResultTy = Context.getPointerType(
- Context.getRecordType(StdSourceLocationImplDecl).withConst());
+ Context.getCanonicalTagType(StdSourceLocationImplDecl).withConst());
break;
}
@@ -18748,7 +18761,9 @@ static bool isVariableCapturable(CapturingScopeInfo *CSI, ValueDecl *Var,
// Prohibit structs with flexible array members too.
// We cannot capture what is in the tail end of the struct.
if (const RecordType *VTTy = Var->getType()->getAs<RecordType>()) {
- if (VTTy->getDecl()->hasFlexibleArrayMember()) {
+ if (VTTy->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->hasFlexibleArrayMember()) {
if (Diagnose) {
if (IsBlock)
S.Diag(Loc, diag::err_ref_flexarray_type);
@@ -21189,7 +21204,7 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
NamedDecl *Temp = *ULE->decls_begin();
const bool IsTypeAliasTemplateDecl = isa<TypeAliasTemplateDecl>(Temp);
- NestedNameSpecifier *NNS = ULE->getQualifierLoc().getNestedNameSpecifier();
+ NestedNameSpecifier NNS = ULE->getQualifierLoc().getNestedNameSpecifier();
// FIXME: AssumedTemplate is not very appropriate for error recovery here,
// as it models only the unqualified-id case, where this case can clearly be
// qualified. Thus we can't just qualify an assumed template.
@@ -21215,16 +21230,16 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
QualType TST;
{
SFINAETrap Trap(*this);
- TST = CheckTemplateIdType(TN, NameInfo.getBeginLoc(), TAL);
+ TST = CheckTemplateIdType(ElaboratedTypeKeyword::None, TN,
+ NameInfo.getBeginLoc(), TAL);
}
if (TST.isNull())
TST = Context.getTemplateSpecializationType(
- TN, ULE->template_arguments(), /*CanonicalArgs=*/{},
+ ElaboratedTypeKeyword::None, TN, ULE->template_arguments(),
+ /*CanonicalArgs=*/{},
HasAnyDependentTA ? Context.DependentTy : Context.IntTy);
- QualType ET =
- Context.getElaboratedType(ElaboratedTypeKeyword::None, NNS, TST);
return CreateRecoveryExpr(NameInfo.getBeginLoc(), NameInfo.getEndLoc(), {},
- ET);
+ TST);
}
// Overloaded expressions.
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index f17a338825423..216f39db4cde6 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -57,11 +57,11 @@ using namespace sema;
ParsedType Sema::getInheritingConstructorName(CXXScopeSpec &SS,
SourceLocation NameLoc,
const IdentifierInfo &Name) {
- NestedNameSpecifier *NNS = SS.getScopeRep();
- if ([[maybe_unused]] const IdentifierInfo *II = NNS->getAsIdentifier())
- assert(II == &Name && "not a constructor name");
+ NestedNameSpecifier NNS = SS.getScopeRep();
+ QualType Type(NNS.getAsType(), 0);
+ if ([[maybe_unused]] const auto *DNT = dyn_cast<DependentNameType>(Type))
+ assert(DNT->getIdentifier() == &Name && "not a constructor name");
- QualType Type(NNS->translateToType(Context), 0);
// This reference to the type is located entirely at the location of the
// final identifier in the qualified-id.
return CreateParsedType(Type,
@@ -111,10 +111,8 @@ ParsedType Sema::getConstructorName(const IdentifierInfo &II,
return ParsedType();
}
- QualType T = Context.getTypeDeclType(InjectedClassName);
- DiagnoseUseOfDecl(InjectedClassName, NameLoc);
- MarkAnyDeclReferenced(NameLoc, InjectedClassName, /*OdrUse=*/false);
-
+ QualType T = Context.getTagType(ElaboratedTypeKeyword::None, SS.getScopeRep(),
+ InjectedClassName, /*OwnsTag=*/false);
return ParsedType::make(T);
}
@@ -175,7 +173,7 @@ ParsedType Sema::getDestructorName(const IdentifierInfo &II,
if (SearchType.isNull() || SearchType->isDependentType())
return true;
- QualType T = Context.getTypeDeclType(Type);
+ CanQualType T = Context.getCanonicalTypeDeclType(Type);
return Context.hasSameUnqualifiedType(T, SearchType);
};
@@ -207,7 +205,8 @@ ParsedType Sema::getDestructorName(const IdentifierInfo &II,
NamedDecl *D = F.next();
if (auto *TD = dyn_cast<TypeDecl>(D->getUnderlyingDecl()))
Diag(D->getLocation(), diag::note_destructor_type_here)
- << Context.getTypeDeclType(TD);
+ << Context.getTypeDeclType(ElaboratedTypeKeyword::None,
+ /*Qualifier=*/std::nullopt, TD);
else
Diag(D->getLocation(), diag::note_destructor_nontype_here);
@@ -222,11 +221,11 @@ ParsedType Sema::getDestructorName(const IdentifierInfo &II,
if (TypeDecl *Type = Found.getAsSingle<TypeDecl>()) {
if (IsAcceptableResult(Type)) {
- QualType T = Context.getTypeDeclType(Type);
+ QualType T = Context.getTypeDeclType(ElaboratedTypeKeyword::None,
+ /*Qualifier=*/std::nullopt, Type);
MarkAnyDeclReferenced(Type->getLocation(), Type, /*OdrUse=*/false);
- return CreateParsedType(
- Context.getElaboratedType(ElaboratedTypeKeyword::None, nullptr, T),
- Context.getTrivialTypeSourceInfo(T, NameLoc));
+ return CreateParsedType(T,
+ Context.getTrivialTypeSourceInfo(T, NameLoc));
}
}
@@ -311,15 +310,23 @@ ParsedType Sema::getDestructorName(const IdentifierInfo &II,
// If both lookups succeed and find a dependent result, which result should
// we retain? (Same question for p->~type-name().)
- if (NestedNameSpecifier *Prefix =
- SS.isSet() ? SS.getScopeRep()->getPrefix() : nullptr) {
+ auto Prefix = [&]() -> NestedNameSpecifierLoc {
+ NestedNameSpecifierLoc NNS = SS.getWithLocInContext(Context);
+ if (!NNS)
+ return NestedNameSpecifierLoc();
+ if (auto TL = NNS.getAsTypeLoc())
+ return TL.getPrefix();
+ return NNS.getAsNamespaceAndPrefix().Prefix;
+ }();
+
+ if (Prefix) {
// This is
//
// nested-name-specifier type-name :: ~ type-name
//
// Look for the second type-name in the nested-name-specifier.
CXXScopeSpec PrefixSS;
- PrefixSS.Adopt(NestedNameSpecifierLoc(Prefix, SS.location_data()));
+ PrefixSS.Adopt(Prefix);
if (ParsedType T = LookupInNestedNameSpec(PrefixSS))
return T;
} else {
@@ -374,7 +381,7 @@ ParsedType Sema::getDestructorName(const IdentifierInfo &II,
//
// also looks for type-name in the scope. Unfortunately, we can't
// reasonably apply this fallback for dependent nested-name-specifiers.
- if (SS.isValid() && SS.getScopeRep()->getPrefix()) {
+ if (Prefix) {
if (ParsedType T = LookupInScope()) {
Diag(SS.getEndLoc(), diag::ext_qualified_dtor_named_in_lexical_scope)
<< FixItHint::CreateRemoval(SS.getRange());
@@ -419,9 +426,10 @@ ParsedType Sema::getDestructorName(const IdentifierInfo &II,
if (auto *TD = dyn_cast<TypeDecl>(FoundDecls[0]->getUnderlyingDecl())) {
assert(!SearchType.isNull() &&
"should only reject a type result if we have a search type");
- QualType T = Context.getTypeDeclType(TD);
Diag(NameLoc, diag::err_destructor_expr_type_mismatch)
- << T << SearchType << MakeFixItHint();
+ << Context.getTypeDeclType(ElaboratedTypeKeyword::None,
+ /*Qualifier=*/std::nullopt, TD)
+ << SearchType << MakeFixItHint();
} else {
Diag(NameLoc, diag::err_destructor_expr_nontype)
<< &II << MakeFixItHint();
@@ -435,7 +443,8 @@ ParsedType Sema::getDestructorName(const IdentifierInfo &II,
for (NamedDecl *FoundD : FoundDecls) {
if (auto *TD = dyn_cast<TypeDecl>(FoundD->getUnderlyingDecl()))
Diag(FoundD->getLocation(), diag::note_destructor_type_here)
- << Context.getTypeDeclType(TD);
+ << Context.getTypeDeclType(ElaboratedTypeKeyword::None,
+ /*Qualifier=*/std::nullopt, TD);
else
Diag(FoundD->getLocation(), diag::note_destructor_nontype_here)
<< FoundD;
@@ -501,12 +510,8 @@ bool Sema::checkLiteralOperatorId(const CXXScopeSpec &SS,
<< II << static_cast<int>(Status) << Hint;
}
- if (!SS.isValid())
- return false;
-
- switch (SS.getScopeRep()->getKind()) {
- case NestedNameSpecifier::Identifier:
- case NestedNameSpecifier::TypeSpec:
+ switch (SS.getScopeRep().getKind()) {
+ case NestedNameSpecifier::Kind::Type:
// Per C++11 [over.literal]p2, literal operators can only be declared at
// namespace scope. Therefore, this unqualified-id cannot name anything.
// Reject it early, because we have no AST representation for this in the
@@ -515,10 +520,10 @@ bool Sema::checkLiteralOperatorId(const CXXScopeSpec &SS,
<< SS.getScopeRep();
return true;
- case NestedNameSpecifier::Global:
- case NestedNameSpecifier::Super:
- case NestedNameSpecifier::Namespace:
- case NestedNameSpecifier::NamespaceAlias:
+ case NestedNameSpecifier::Kind::Null:
+ case NestedNameSpecifier::Kind::Global:
+ case NestedNameSpecifier::Kind::Super:
+ case NestedNameSpecifier::Kind::Namespace:
return false;
}
@@ -566,7 +571,8 @@ ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
QualType T = E->getType();
if (const RecordType *RecordT = T->getAs<RecordType>()) {
- CXXRecordDecl *RecordD = cast<CXXRecordDecl>(RecordT->getDecl());
+ CXXRecordDecl *RecordD = cast<CXXRecordDecl>(RecordT->getOriginalDecl())
+ ->getDefinitionOrSelf();
// C++ [expr.typeid]p3:
// [...] If the type of the expression is a class type, the class
// shall be completely-defined.
@@ -660,7 +666,7 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,
return ExprError(Diag(OpLoc, diag::err_no_typeid_with_fno_rtti));
}
- QualType TypeInfoType = Context.getTypeDeclType(CXXTypeInfoDecl);
+ CanQualType TypeInfoType = Context.getCanonicalTagType(CXXTypeInfoDecl);
if (isType) {
// The operand is a type; handle it as such.
@@ -1215,7 +1221,7 @@ QualType Sema::getCurrentThisType() {
// This is a lambda call operator that is being instantiated as a default
// initializer. DC must point to the enclosing class type, so we can recover
// the 'this' type from it.
- QualType ClassTy = Context.getTypeDeclType(cast<CXXRecordDecl>(DC));
+ CanQualType ClassTy = Context.getCanonicalTagType(cast<CXXRecordDecl>(DC));
// There are no cv-qualifiers for 'this' within default initializers,
// per [expr.prim.general]p4.
ThisTy = Context.getPointerType(ClassTy);
@@ -1245,7 +1251,7 @@ Sema::CXXThisScopeRAII::CXXThisScopeRAII(Sema &S,
else
Record = cast<CXXRecordDecl>(ContextDecl);
- QualType T = S.Context.getRecordType(Record);
+ QualType T = S.Context.getCanonicalTagType(Record);
T = S.getASTContext().getQualifiedType(T, CXXThisTypeQuals);
S.CXXThisTypeOverride =
@@ -1733,7 +1739,7 @@ static bool isNonPlacementDeallocationFunction(Sema &S, FunctionDecl *FD) {
if (S.getLangOpts().AlignedAllocation && UsualParams < FD->getNumParams() &&
S.Context.hasSameUnqualifiedType(
FD->getParamDecl(UsualParams)->getType(),
- S.Context.getTypeDeclType(S.getStdAlignValT())))
+ S.Context.getCanonicalTagType(S.getStdAlignValT())))
++UsualParams;
return UsualParams == FD->getNumParams();
@@ -1861,8 +1867,8 @@ namespace {
if (FunctionTemplateDecl *Best = S.getMoreSpecializedTemplate(
PrimaryTemplate, OtherPrimaryTemplate, SourceLocation(),
TPOC_Call, ImplicitArgCount,
- DC ? QualType(DC->getTypeForDecl(), 0) : QualType{},
- OtherDC ? QualType(OtherDC->getTypeForDecl(), 0) : QualType{},
+ DC ? S.Context.getCanonicalTagType(DC) : QualType{},
+ OtherDC ? S.Context.getCanonicalTagType(OtherDC) : QualType{},
false)) {
return Best == PrimaryTemplate ? 1 : -1;
}
@@ -1978,7 +1984,7 @@ static bool doesUsualArrayDeleteWantSize(Sema &S, SourceLocation loc,
DeclarationName deleteName =
S.Context.DeclarationNames.getCXXOperatorName(OO_Array_Delete);
LookupResult ops(S, deleteName, loc, Sema::LookupOrdinaryName);
- S.LookupQualifiedName(ops, record->getDecl());
+ S.LookupQualifiedName(ops, record->getOriginalDecl()->getDefinitionOrSelf());
// We're just doing this for information.
ops.suppressDiagnostics();
@@ -2506,7 +2512,7 @@ ExprResult Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
// because there might not be a `std::align_val_t` type.
EnumDecl *StdAlignValT = getStdAlignValT();
QualType AlignValT =
- StdAlignValT ? Context.getTypeDeclType(StdAlignValT) : SizeTy;
+ StdAlignValT ? Context.getCanonicalTagType(StdAlignValT) : SizeTy;
IntegerLiteral AlignmentLiteral(
Context,
llvm::APInt(Context.getTypeSize(SizeTy),
@@ -2957,7 +2963,7 @@ bool Sema::FindAllocationFunctions(
isTypeAwareAllocation(IAP.PassTypeIdentity);
if (IncludeAlignParam) {
DeclareGlobalNewDelete();
- AlignValT = Context.getTypeDeclType(getStdAlignValT());
+ AlignValT = Context.getCanonicalTagType(getStdAlignValT());
}
CXXScalarValueInitExpr Align(AlignValT, nullptr, SourceLocation());
if (IncludeAlignParam)
@@ -3039,8 +3045,9 @@ bool Sema::FindAllocationFunctions(
LookupResult FoundDelete(*this, DeleteName, StartLoc, LookupOrdinaryName);
if (AllocElemType->isRecordType() &&
DeleteScope != AllocationFunctionScope::Global) {
- auto *RD =
- cast<CXXRecordDecl>(AllocElemType->castAs<RecordType>()->getDecl());
+ auto *RD = cast<CXXRecordDecl>(
+ AllocElemType->castAs<RecordType>()->getOriginalDecl())
+ ->getDefinitionOrSelf();
LookupQualifiedName(FoundDelete, RD);
}
if (FoundDelete.isAmbiguous())
@@ -3417,7 +3424,7 @@ void Sema::DeclareGlobalNewDelete() {
for (int Aligned = 0; Aligned < NumAlignVariants; ++Aligned) {
if (Aligned)
- Params.push_back(Context.getTypeDeclType(getStdAlignValT()));
+ Params.push_back(Context.getCanonicalTagType(getStdAlignValT()));
DeclareGlobalAllocationFunction(
Context.DeclarationNames.getCXXOperatorName(Kind), Return, Params);
@@ -3474,7 +3481,7 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
bool HasBadAllocExceptionSpec = Name.isAnyOperatorNew();
if (HasBadAllocExceptionSpec) {
if (!getLangOpts().CPlusPlus11) {
- BadAllocType = Context.getTypeDeclType(getStdBadAlloc());
+ BadAllocType = Context.getCanonicalTagType(getStdBadAlloc());
assert(StdBadAlloc && "Must have std::bad_alloc declared");
EPI.ExceptionSpec.Type = EST_Dynamic;
EPI.ExceptionSpec.Exceptions = llvm::ArrayRef(BadAllocType);
@@ -3584,7 +3591,7 @@ FunctionDecl *Sema::FindDeallocationFunctionForDestructor(SourceLocation Loc,
DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Delete);
FunctionDecl *OperatorDelete = nullptr;
- QualType DeallocType = Context.getRecordType(RD);
+ CanQualType DeallocType = Context.getCanonicalTagType(RD);
ImplicitDeallocationParameters IDP = {
DeallocType, ShouldUseTypeAwareOperatorNewOrDelete(),
AlignedAllocationMode::No, SizedDeallocationMode::No};
@@ -3618,7 +3625,7 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
Found.suppressDiagnostics();
if (!isAlignedAllocation(IDP.PassAlignment) &&
- hasNewExtendedAlignment(*this, Context.getRecordType(RD)))
+ hasNewExtendedAlignment(*this, Context.getCanonicalTagType(RD)))
IDP.PassAlignment = AlignedAllocationMode::Yes;
// C++17 [expr.delete]p10:
@@ -4041,7 +4048,8 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
: diag::warn_delete_incomplete,
Ex.get())) {
if (const RecordType *RT = PointeeElem->getAs<RecordType>())
- PointeeRD = cast<CXXRecordDecl>(RT->getDecl());
+ PointeeRD =
+ cast<CXXRecordDecl>(RT->getOriginalDecl())->getDefinitionOrSelf();
}
}
@@ -4566,7 +4574,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
// If the user-defined conversion is specified by a conversion function,
// the initial standard conversion sequence converts the source type to
// the implicit object parameter of the conversion function.
- BeforeToType = Context.getTagDeclType(Conv->getParent());
+ BeforeToType = Context.getCanonicalTagType(Conv->getParent());
} else {
const CXXConstructorDecl *Ctor = cast<CXXConstructorDecl>(FD);
CastKind = CK_ConstructorConversion;
@@ -4810,7 +4818,10 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
if (FromType->isVectorType() || ToType->isVectorType())
StepTy = adjustVectorType(Context, FromType, ToType, &ElTy);
if (ElTy->isBooleanType()) {
- assert(FromType->castAs<EnumType>()->getDecl()->isFixed() &&
+ assert(FromType->castAs<EnumType>()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->isFixed() &&
SCS.Second == ICK_Integral_Promotion &&
"only enums with fixed underlying type can promote to bool");
From = ImpCastExprToType(From, StepTy, CK_IntegralToBoolean, VK_PRValue,
@@ -5362,16 +5373,18 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &LHS, ExprResult &RHS,
return QualType();
}
+ // FIXME: use sugared type from member pointer.
+ CanQualType RHSClassType = Context.getCanonicalTagType(RHSClass);
CXXCastPath BasePath;
if (CheckDerivedToBaseConversion(
- LHSType, QualType(RHSClass->getTypeForDecl(), 0), Loc,
+ LHSType, RHSClassType, Loc,
SourceRange(LHS.get()->getBeginLoc(), RHS.get()->getEndLoc()),
&BasePath))
return QualType();
// Cast LHS to type of use.
- QualType UseType = Context.getQualifiedType(RHSClass->getTypeForDecl(),
- LHSType.getQualifiers());
+ QualType UseType =
+ Context.getQualifiedType(RHSClassType, LHSType.getQualifiers());
if (isIndirect)
UseType = Context.getPointerType(UseType);
ExprValueKind VK = isIndirect ? VK_PRValue : LHS.get()->getValueKind();
@@ -6176,7 +6189,7 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc,
case Pointer:
return Ctx.getPointerType(T);
case MemberPointer:
- return Ctx.getMemberPointerType(T, /*Qualifier=*/nullptr,
+ return Ctx.getMemberPointerType(T, /*Qualifier=*/std::nullopt,
ClassOrBound->getAsCXXRecordDecl());
case ObjCPointer:
return Ctx.getObjCObjectPointerType(T);
@@ -6349,7 +6362,7 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc,
return QualType();
Steps.emplace_back(Step::MemberPointer,
- Context.getTypeDeclType(Cls).getTypePtr());
+ Context.getCanonicalTagType(Cls).getTypePtr());
continue;
}
@@ -6628,7 +6641,8 @@ ExprResult Sema::MaybeBindToTemporary(Expr *E) {
// That should be enough to guarantee that this type is complete, if we're
// not processing a decltype expression.
- CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ CXXRecordDecl *RD =
+ cast<CXXRecordDecl>(RT->getOriginalDecl())->getDefinitionOrSelf();
if (RD->isInvalidDecl() || RD->isDependentContext())
return E;
@@ -7235,16 +7249,13 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
TemplateIdAnnotation *TemplateId = SecondTypeName.TemplateId;
ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),
TemplateId->NumArgs);
- TypeResult T = ActOnTemplateIdType(S,
- SS,
- TemplateId->TemplateKWLoc,
- TemplateId->Template,
- TemplateId->Name,
- TemplateId->TemplateNameLoc,
- TemplateId->LAngleLoc,
- TemplateArgsPtr,
- TemplateId->RAngleLoc,
- /*IsCtorOrDtorName*/true);
+ TypeResult T = ActOnTemplateIdType(
+ S, ElaboratedTypeKeyword::None,
+ /*ElaboratedKeywordLoc=*/SourceLocation(), SS,
+ TemplateId->TemplateKWLoc, TemplateId->Template, TemplateId->Name,
+ TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, TemplateArgsPtr,
+ TemplateId->RAngleLoc,
+ /*IsCtorOrDtorName*/ true);
if (T.isInvalid() || !T.get()) {
// Recover by assuming we had the right type all along.
DestructedType = ObjectType;
@@ -7288,16 +7299,13 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
TemplateIdAnnotation *TemplateId = FirstTypeName.TemplateId;
ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),
TemplateId->NumArgs);
- TypeResult T = ActOnTemplateIdType(S,
- SS,
- TemplateId->TemplateKWLoc,
- TemplateId->Template,
- TemplateId->Name,
- TemplateId->TemplateNameLoc,
- TemplateId->LAngleLoc,
- TemplateArgsPtr,
- TemplateId->RAngleLoc,
- /*IsCtorOrDtorName*/true);
+ TypeResult T = ActOnTemplateIdType(
+ S, ElaboratedTypeKeyword::None,
+ /*ElaboratedKeywordLoc=*/SourceLocation(), SS,
+ TemplateId->TemplateKWLoc, TemplateId->Template, TemplateId->Name,
+ TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, TemplateArgsPtr,
+ TemplateId->RAngleLoc,
+ /*IsCtorOrDtorName*/ true);
if (T.isInvalid() || !T.get()) {
// Recover by dropping this type.
ScopeType = QualType();
@@ -7497,7 +7505,7 @@ ExprResult Sema::IgnoredValueConversions(Expr *E) {
// GCC seems to also exclude expressions of incomplete enum type.
if (const EnumType *T = E->getType()->getAs<EnumType>()) {
- if (!T->getDecl()->isComplete()) {
+ if (!T->getOriginalDecl()->getDefinitionOrSelf()->isComplete()) {
// FIXME: stupid workaround for a codegen bug!
E = ImpCastExprToType(E, Context.VoidTy, CK_ToVoid).get();
return E;
diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp
index 5dca509d46fdb..4a31a139eaf4f 100644
--- a/clang/lib/Sema/SemaExprMember.cpp
+++ b/clang/lib/Sema/SemaExprMember.cpp
@@ -492,13 +492,14 @@ CheckExtVectorComponent(Sema &S, QualType baseType, ExprValueKind &VK,
QualType VT = S.Context.getExtVectorType(vecType->getElementType(), CompSize);
// Now look up the TypeDefDecl from the vector type. Without this,
- // diagostics look bad. We want extended vector types to appear built-in.
+ // diagnostics look bad. We want extended vector types to appear built-in.
for (Sema::ExtVectorDeclsType::iterator
I = S.ExtVectorDecls.begin(S.getExternalSource()),
E = S.ExtVectorDecls.end();
I != E; ++I) {
if ((*I)->getUnderlyingType() == VT)
- return S.Context.getTypedefType(*I);
+ return S.Context.getTypedefType(ElaboratedTypeKeyword::None,
+ /*Qualifier=*/std::nullopt, *I);
}
return VT; // should never get here (a typedef type should always be found).
@@ -881,7 +882,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
// build a CXXDependentScopeMemberExpr.
if (R.wasNotFoundInCurrentInstantiation() ||
(R.getLookupName().getCXXOverloadedOperator() == OO_Equal &&
- (SS.isSet() ? SS.getScopeRep()->isDependent()
+ (SS.isSet() ? SS.getScopeRep().isDependent()
: BaseExprType->isDependentType())))
return ActOnDependentMemberExpr(BaseExpr, BaseExprType, IsArrow, OpLoc, SS,
TemplateKWLoc, FirstQualifierInScope,
diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp
index e0662d82914f4..03b5c79cf70e3 100644
--- a/clang/lib/Sema/SemaExprObjC.cpp
+++ b/clang/lib/Sema/SemaExprObjC.cpp
@@ -639,14 +639,14 @@ ExprResult SemaObjC::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
BoxingMethod = getNSNumberFactoryMethod(*this, Loc, ValueType);
BoxedType = NSNumberPointer;
} else if (const EnumType *ET = ValueType->getAs<EnumType>()) {
- if (!ET->getDecl()->isComplete()) {
+ const EnumDecl *ED = ET->getOriginalDecl()->getDefinitionOrSelf();
+ if (!ED->isComplete()) {
Diag(Loc, diag::err_objc_incomplete_boxed_expression_type)
<< ValueType << ValueExpr->getSourceRange();
return ExprError();
}
- BoxingMethod = getNSNumberFactoryMethod(*this, Loc,
- ET->getDecl()->getIntegerType());
+ BoxingMethod = getNSNumberFactoryMethod(*this, Loc, ED->getIntegerType());
BoxedType = NSNumberPointer;
} else if (ValueType->isObjCBoxableRecordType()) {
// Support for structure types, that marked as objc_boxable
@@ -2337,10 +2337,10 @@ SemaObjC::getObjCMessageKind(Scope *S, IdentifierInfo *Name,
if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(ND))
T = Context.getObjCInterfaceType(Class);
else if (TypeDecl *Type = dyn_cast<TypeDecl>(ND)) {
- T = Context.getTypeDeclType(Type);
SemaRef.DiagnoseUseOfDecl(Type, NameLoc);
- }
- else
+ T = Context.getTypeDeclType(ElaboratedTypeKeyword::None,
+ /*Qualifier=*/std::nullopt, Type);
+ } else
return ObjCInstanceMessage;
// We have a class message, and T is the type we're
@@ -3847,7 +3847,8 @@ static inline T *getObjCBridgeAttr(const TypedefType *TD) {
if (QT->isPointerType()) {
QT = QT->getPointeeType();
if (const RecordType *RT = QT->getAs<RecordType>()) {
- for (auto *Redecl : RT->getDecl()->getMostRecentDecl()->redecls()) {
+ for (auto *Redecl :
+ RT->getOriginalDecl()->getMostRecentDecl()->redecls()) {
if (auto *attr = Redecl->getAttr<T>())
return attr;
}
diff --git a/clang/lib/Sema/SemaFunctionEffects.cpp b/clang/lib/Sema/SemaFunctionEffects.cpp
index 1592862416bf9..8590ee831084f 100644
--- a/clang/lib/Sema/SemaFunctionEffects.cpp
+++ b/clang/lib/Sema/SemaFunctionEffects.cpp
@@ -1352,11 +1352,15 @@ class Analyzer {
return true;
}
- bool TraverseTypeOfExprTypeLoc(TypeOfExprTypeLoc Node) override {
+ bool TraverseTypeOfExprTypeLoc(TypeOfExprTypeLoc Node,
+ bool TraverseQualifier) override {
return true;
}
- bool TraverseDecltypeTypeLoc(DecltypeTypeLoc Node) override { return true; }
+ bool TraverseDecltypeTypeLoc(DecltypeTypeLoc Node,
+ bool TraverseQualifier) override {
+ return true;
+ }
bool TraverseCXXNoexceptExpr(CXXNoexceptExpr *Node) override {
return true;
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 968b96990bd85..7c134d404e143 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -231,7 +231,7 @@ static unsigned calculateLegacyCbufferSize(const ASTContext &Context,
constexpr unsigned CBufferAlign = 16;
if (const RecordType *RT = T->getAs<RecordType>()) {
unsigned Size = 0;
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
for (const FieldDecl *Field : RD->fields()) {
QualType Ty = Field->getType();
unsigned FieldSize = calculateLegacyCbufferSize(Context, Ty);
@@ -370,7 +370,7 @@ static bool isInvalidConstantBufferLeafElementType(const Type *Ty) {
// needs to be created for HLSL Buffer use that will exclude these unwanted
// declarations (see createHostLayoutStruct function).
static bool requiresImplicitBufferLayoutStructure(const CXXRecordDecl *RD) {
- if (RD->getTypeForDecl()->isHLSLIntangibleType() || RD->isEmpty())
+ if (RD->isHLSLIntangible() || RD->isEmpty())
return true;
// check fields
for (const FieldDecl *Field : RD->fields()) {
@@ -455,7 +455,7 @@ static FieldDecl *createFieldForHostLayoutStruct(Sema &S, const Type *Ty,
RD = createHostLayoutStruct(S, RD);
if (!RD)
return nullptr;
- Ty = RD->getTypeForDecl();
+ Ty = S.Context.getCanonicalTagType(RD)->getTypePtr();
}
}
@@ -505,8 +505,8 @@ static CXXRecordDecl *createHostLayoutStruct(Sema &S,
if (requiresImplicitBufferLayoutStructure(BaseDecl)) {
BaseDecl = createHostLayoutStruct(S, BaseDecl);
if (BaseDecl) {
- TypeSourceInfo *TSI = AST.getTrivialTypeSourceInfo(
- QualType(BaseDecl->getTypeForDecl(), 0));
+ TypeSourceInfo *TSI =
+ AST.getTrivialTypeSourceInfo(AST.getCanonicalTagType(BaseDecl));
Base = CXXBaseSpecifier(SourceRange(), false, StructDecl->isClass(),
AS_none, TSI, SourceLocation());
}
@@ -1744,7 +1744,7 @@ SemaHLSL::TakeLocForHLSLAttribute(const HLSLAttributedResourceType *RT) {
// requirements and adds them to Bindings
void SemaHLSL::collectResourceBindingsOnUserRecordDecl(const VarDecl *VD,
const RecordType *RT) {
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
for (FieldDecl *FD : RD->fields()) {
const Type *Ty = FD->getType()->getUnqualifiedDesugaredType();
@@ -3297,7 +3297,7 @@ bool SemaHLSL::ContainsBitField(QualType BaseTy) {
continue;
}
if (const auto *RT = dyn_cast<RecordType>(T)) {
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
if (RD->isUnion())
continue;
@@ -3813,7 +3813,8 @@ class InitListTransformer {
}
while (!RecordTypes.empty()) {
const RecordType *RT = RecordTypes.pop_back_val();
- for (auto *FD : RT->getDecl()->fields()) {
+ for (auto *FD :
+ RT->getOriginalDecl()->getDefinitionOrSelf()->fields()) {
DeclAccessPair Found = DeclAccessPair::make(FD, FD->getAccess());
DeclarationNameInfo NameInfo(FD->getDeclName(), E->getBeginLoc());
ExprResult Res = S.BuildFieldReferenceExpr(
@@ -3861,7 +3862,8 @@ class InitListTransformer {
}
while (!RecordTypes.empty()) {
const RecordType *RT = RecordTypes.pop_back_val();
- for (auto *FD : RT->getDecl()->fields()) {
+ for (auto *FD :
+ RT->getOriginalDecl()->getDefinitionOrSelf()->fields()) {
Inits.push_back(generateInitListsImpl(FD->getType()));
}
}
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 0844cb4d6c3cd..a8bfddbfe4191 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -446,7 +446,6 @@ class InitListChecker {
unsigned ExpectedNumInits);
int numArrayElements(QualType DeclType);
int numStructUnionElements(QualType DeclType);
- static RecordDecl *getRecordDecl(QualType DeclType);
ExprResult PerformEmptyInit(SourceLocation Loc,
const InitializedEntity &Entity);
@@ -776,7 +775,7 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field,
if (Init >= NumInits || !ILE->getInit(Init)) {
if (const RecordType *RType = ILE->getType()->getAs<RecordType>())
- if (!RType->getDecl()->isUnion())
+ if (!RType->getOriginalDecl()->isUnion())
assert((Init < NumInits || VerifyOnly) &&
"This ILE should have been expanded");
@@ -922,7 +921,7 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity,
return;
if (const RecordType *RType = ILE->getType()->getAs<RecordType>()) {
- const RecordDecl *RDecl = RType->getDecl();
+ const RecordDecl *RDecl = RType->getOriginalDecl()->getDefinitionOrSelf();
if (RDecl->isUnion() && ILE->getInitializedFieldInUnion()) {
FillInEmptyInitForField(0, ILE->getInitializedFieldInUnion(), Entity, ILE,
RequiresSecondPass, FillWithNoInit);
@@ -1126,7 +1125,8 @@ int InitListChecker::numArrayElements(QualType DeclType) {
}
int InitListChecker::numStructUnionElements(QualType DeclType) {
- RecordDecl *structDecl = DeclType->castAs<RecordType>()->getDecl();
+ RecordDecl *structDecl =
+ DeclType->castAs<RecordType>()->getOriginalDecl()->getDefinitionOrSelf();
int InitializableMembers = 0;
if (auto *CXXRD = dyn_cast<CXXRecordDecl>(structDecl))
InitializableMembers += CXXRD->getNumBases();
@@ -1139,14 +1139,6 @@ int InitListChecker::numStructUnionElements(QualType DeclType) {
return InitializableMembers - structDecl->hasFlexibleArrayMember();
}
-RecordDecl *InitListChecker::getRecordDecl(QualType DeclType) {
- if (const auto *RT = DeclType->getAs<RecordType>())
- return RT->getDecl();
- if (const auto *Inject = DeclType->getAs<InjectedClassNameType>())
- return Inject->getDecl();
- return nullptr;
-}
-
/// Determine whether Entity is an entity for which it is idiomatic to elide
/// the braces in aggregate initialization.
static bool isIdiomaticBraceElisionEntity(const InitializedEntity &Entity) {
@@ -1163,16 +1155,22 @@ static bool isIdiomaticBraceElisionEntity(const InitializedEntity &Entity) {
// Allows elide brace initialization for aggregates with empty base.
if (Entity.getKind() == InitializedEntity::EK_Base) {
- auto *ParentRD =
- Entity.getParent()->getType()->castAs<RecordType>()->getDecl();
+ auto *ParentRD = Entity.getParent()
+ ->getType()
+ ->castAs<RecordType>()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf();
CXXRecordDecl *CXXRD = cast<CXXRecordDecl>(ParentRD);
return CXXRD->getNumBases() == 1 && CXXRD->field_empty();
}
// Allow brace elision if the only subobject is a field.
if (Entity.getKind() == InitializedEntity::EK_Member) {
- auto *ParentRD =
- Entity.getParent()->getType()->castAs<RecordType>()->getDecl();
+ auto *ParentRD = Entity.getParent()
+ ->getType()
+ ->castAs<RecordType>()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf();
if (CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(ParentRD)) {
if (CXXRD->getNumBases()) {
return false;
@@ -1441,7 +1439,7 @@ void InitListChecker::CheckListElementTypes(const InitializedEntity &Entity,
} else if (DeclType->isVectorType()) {
CheckVectorType(Entity, IList, DeclType, Index,
StructuredList, StructuredIndex);
- } else if (const RecordDecl *RD = getRecordDecl(DeclType)) {
+ } else if (const RecordDecl *RD = DeclType->getAsRecordDecl()) {
auto Bases =
CXXRecordDecl::base_class_const_range(CXXRecordDecl::base_class_const_iterator(),
CXXRecordDecl::base_class_const_iterator());
@@ -2319,7 +2317,7 @@ void InitListChecker::CheckStructUnionTypes(
bool SubobjectIsDesignatorContext, unsigned &Index,
InitListExpr *StructuredList, unsigned &StructuredIndex,
bool TopLevelObject) {
- const RecordDecl *RD = getRecordDecl(DeclType);
+ const RecordDecl *RD = DeclType->getAsRecordDecl();
// If the record is invalid, some of it's members are invalid. To avoid
// confusion, we forgo checking the initializer for the entire record.
@@ -2888,7 +2886,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
// then the current object (defined below) shall have
// structure or union type and the identifier shall be the
// name of a member of that type.
- RecordDecl *RD = getRecordDecl(CurrentObjectType);
+ RecordDecl *RD = CurrentObjectType->getAsRecordDecl();
if (!RD) {
SourceLocation Loc = D->getDotLoc();
if (Loc.isInvalid())
@@ -4336,8 +4334,8 @@ static bool hasCopyOrMoveCtorParam(ASTContext &Ctx,
QualType ParmT =
Info.Constructor->getParamDecl(0)->getType().getNonReferenceType();
- QualType ClassT =
- Ctx.getRecordType(cast<CXXRecordDecl>(Info.FoundDecl->getDeclContext()));
+ CanQualType ClassT = Ctx.getCanonicalTagType(
+ cast<CXXRecordDecl>(Info.FoundDecl->getDeclContext()));
return Ctx.hasSameUnqualifiedType(ParmT, ClassT);
}
@@ -4536,8 +4534,8 @@ static void TryConstructorInitialization(Sema &S,
const RecordType *DestRecordType = DestType->getAs<RecordType>();
assert(DestRecordType && "Constructor initialization requires record type");
- CXXRecordDecl *DestRecordDecl
- = cast<CXXRecordDecl>(DestRecordType->getDecl());
+ auto *DestRecordDecl = cast<CXXRecordDecl>(DestRecordType->getOriginalDecl())
+ ->getDefinitionOrSelf();
// Build the candidate set directly in the initialization sequence
// structure, so that it will persist if we fail.
@@ -5057,8 +5055,8 @@ static void TryListInitialization(Sema &S,
// the underlying type of T, the program is ill-formed.
auto *ET = DestType->getAs<EnumType>();
if (S.getLangOpts().CPlusPlus17 &&
- Kind.getKind() == InitializationKind::IK_DirectList &&
- ET && ET->getDecl()->isFixed() &&
+ Kind.getKind() == InitializationKind::IK_DirectList && ET &&
+ ET->getOriginalDecl()->getDefinitionOrSelf()->isFixed() &&
!S.Context.hasSameUnqualifiedType(E->getType(), DestType) &&
(E->getType()->isIntegralOrUnscopedEnumerationType() ||
E->getType()->isFloatingType())) {
@@ -5168,7 +5166,8 @@ static OverloadingResult TryRefInitWithConversionFunction(
S.isCompleteType(Kind.getLocation(), T1)) {
// The type we're converting to is a class type. Enumerate its constructors
// to see if there is a suitable conversion.
- CXXRecordDecl *T1RecordDecl = cast<CXXRecordDecl>(T1RecordType->getDecl());
+ auto *T1RecordDecl = cast<CXXRecordDecl>(T1RecordType->getOriginalDecl())
+ ->getDefinitionOrSelf();
for (NamedDecl *D : S.LookupConstructors(T1RecordDecl)) {
auto Info = getConstructorInfo(D);
@@ -5191,7 +5190,8 @@ static OverloadingResult TryRefInitWithConversionFunction(
}
}
}
- if (T1RecordType && T1RecordType->getDecl()->isInvalidDecl())
+ if (T1RecordType &&
+ T1RecordType->getOriginalDecl()->getDefinitionOrSelf()->isInvalidDecl())
return OR_No_Viable_Function;
const RecordType *T2RecordType = nullptr;
@@ -5199,7 +5199,8 @@ static OverloadingResult TryRefInitWithConversionFunction(
S.isCompleteType(Kind.getLocation(), T2)) {
// The type we're converting from is a class type, enumerate its conversion
// functions.
- CXXRecordDecl *T2RecordDecl = cast<CXXRecordDecl>(T2RecordType->getDecl());
+ auto *T2RecordDecl = cast<CXXRecordDecl>(T2RecordType->getOriginalDecl())
+ ->getDefinitionOrSelf();
const auto &Conversions = T2RecordDecl->getVisibleConversionFunctions();
for (auto I = Conversions.begin(), E = Conversions.end(); I != E; ++I) {
@@ -5235,7 +5236,8 @@ static OverloadingResult TryRefInitWithConversionFunction(
}
}
}
- if (T2RecordType && T2RecordType->getDecl()->isInvalidDecl())
+ if (T2RecordType &&
+ T2RecordType->getOriginalDecl()->getDefinitionOrSelf()->isInvalidDecl())
return OR_No_Viable_Function;
SourceLocation DeclLoc = Initializer->getBeginLoc();
@@ -5713,7 +5715,9 @@ static void TryValueInitialization(Sema &S,
T = S.Context.getBaseElementType(T);
if (const RecordType *RT = T->getAs<RecordType>()) {
- if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
+ if (CXXRecordDecl *ClassDecl =
+ dyn_cast<CXXRecordDecl>(RT->getOriginalDecl())) {
+ ClassDecl = ClassDecl->getDefinitionOrSelf();
bool NeedZeroInitialization = true;
// C++98:
// -- if T is a class type (clause 9) with a user-declared constructor
@@ -5911,7 +5915,8 @@ static void TryOrBuildParenListInitialization(
}
} else if (auto *RT = Entity.getType()->getAs<RecordType>()) {
bool IsUnion = RT->isUnionType();
- const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ const auto *RD =
+ cast<CXXRecordDecl>(RT->getOriginalDecl())->getDefinitionOrSelf();
if (RD->isInvalidDecl()) {
// Exit early to avoid confusion when processing members.
// We do the same for braced list initialization in
@@ -6099,8 +6104,9 @@ static void TryUserDefinedConversion(Sema &S,
if (const RecordType *DestRecordType = DestType->getAs<RecordType>()) {
// The type we're converting to is a class type. Enumerate its constructors
// to see if there is a suitable conversion.
- CXXRecordDecl *DestRecordDecl
- = cast<CXXRecordDecl>(DestRecordType->getDecl());
+ auto *DestRecordDecl =
+ cast<CXXRecordDecl>(DestRecordType->getOriginalDecl())
+ ->getDefinitionOrSelf();
// Try to complete the type we're converting to.
if (S.isCompleteType(Kind.getLocation(), DestType)) {
@@ -6136,8 +6142,9 @@ static void TryUserDefinedConversion(Sema &S,
// We can only enumerate the conversion functions for a complete type; if
// the type isn't complete, simply skip this step.
if (S.isCompleteType(DeclLoc, SourceType)) {
- CXXRecordDecl *SourceRecordDecl
- = cast<CXXRecordDecl>(SourceRecordType->getDecl());
+ auto *SourceRecordDecl =
+ cast<CXXRecordDecl>(SourceRecordType->getOriginalDecl())
+ ->getDefinitionOrSelf();
const auto &Conversions =
SourceRecordDecl->getVisibleConversionFunctions();
@@ -7170,7 +7177,8 @@ static ExprResult CopyObject(Sema &S,
Expr *CurInitExpr = (Expr *)CurInit.get();
CXXRecordDecl *Class = nullptr;
if (const RecordType *Record = T->getAs<RecordType>())
- Class = cast<CXXRecordDecl>(Record->getDecl());
+ Class =
+ cast<CXXRecordDecl>(Record->getOriginalDecl())->getDefinitionOrSelf();
if (!Class)
return CurInit;
@@ -7325,8 +7333,8 @@ static void CheckCXX98CompatAccessibleCopy(Sema &S,
// Find constructors which would have been considered.
OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
- DeclContext::lookup_result Ctors =
- S.LookupConstructors(cast<CXXRecordDecl>(Record->getDecl()));
+ DeclContext::lookup_result Ctors = S.LookupConstructors(
+ cast<CXXRecordDecl>(Record->getOriginalDecl())->getDefinitionOrSelf());
// Perform overload resolution.
OverloadCandidateSet::iterator Best;
@@ -8156,8 +8164,9 @@ ExprResult InitializationSequence::Perform(Sema &S,
// regardless of how we initialized the entity.
QualType T = CurInit.get()->getType();
if (const RecordType *Record = T->getAs<RecordType>()) {
- CXXDestructorDecl *Destructor
- = S.LookupDestructor(cast<CXXRecordDecl>(Record->getDecl()));
+ CXXDestructorDecl *Destructor =
+ S.LookupDestructor(cast<CXXRecordDecl>(Record->getOriginalDecl())
+ ->getDefinitionOrSelf());
S.CheckDestructorAccess(CurInit.get()->getBeginLoc(), Destructor,
S.PDiag(diag::err_access_dtor_temp) << T);
S.MarkFunctionReferenced(CurInit.get()->getBeginLoc(), Destructor);
@@ -8804,8 +8813,8 @@ static void emitBadConversionNotes(Sema &S, const InitializedEntity &entity,
destPointeeType.getQualifiers().compatiblyIncludes(
fromPointeeType.getQualifiers(), S.getASTContext()))
S.Diag(fromDecl->getLocation(), diag::note_forward_class_conversion)
- << S.getASTContext().getTagDeclType(fromDecl)
- << S.getASTContext().getTagDeclType(destDecl);
+ << S.getASTContext().getCanonicalTagType(fromDecl)
+ << S.getASTContext().getCanonicalTagType(destDecl);
}
static void diagnoseListInit(Sema &S, const InitializedEntity &Entity,
@@ -9204,32 +9213,34 @@ bool InitializationSequence::Diagnose(Sema &S,
InheritedFrom = Inherited.getShadowDecl()->getNominatedBaseClass();
if (Entity.getKind() == InitializedEntity::EK_Base) {
S.Diag(Kind.getLocation(), diag::err_missing_default_ctor)
- << (InheritedFrom ? 2 : Constructor->isImplicit() ? 1 : 0)
- << S.Context.getTypeDeclType(Constructor->getParent())
- << /*base=*/0
- << Entity.getType()
- << InheritedFrom;
-
- RecordDecl *BaseDecl
- = Entity.getBaseSpecifier()->getType()->castAs<RecordType>()
- ->getDecl();
+ << (InheritedFrom ? 2
+ : Constructor->isImplicit() ? 1
+ : 0)
+ << S.Context.getCanonicalTagType(Constructor->getParent())
+ << /*base=*/0 << Entity.getType() << InheritedFrom;
+
+ RecordDecl *BaseDecl = Entity.getBaseSpecifier()
+ ->getType()
+ ->castAs<RecordType>()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf();
S.Diag(BaseDecl->getLocation(), diag::note_previous_decl)
- << S.Context.getTagDeclType(BaseDecl);
+ << S.Context.getCanonicalTagType(BaseDecl);
} else {
S.Diag(Kind.getLocation(), diag::err_missing_default_ctor)
- << (InheritedFrom ? 2 : Constructor->isImplicit() ? 1 : 0)
- << S.Context.getTypeDeclType(Constructor->getParent())
- << /*member=*/1
- << Entity.getName()
- << InheritedFrom;
+ << (InheritedFrom ? 2
+ : Constructor->isImplicit() ? 1
+ : 0)
+ << S.Context.getCanonicalTagType(Constructor->getParent())
+ << /*member=*/1 << Entity.getName() << InheritedFrom;
S.Diag(Entity.getDecl()->getLocation(),
diag::note_member_declared_at);
if (const RecordType *Record
= Entity.getType()->getAs<RecordType>())
- S.Diag(Record->getDecl()->getLocation(),
+ S.Diag(Record->getOriginalDecl()->getLocation(),
diag::note_previous_decl)
- << S.Context.getTagDeclType(Record->getDecl());
+ << S.Context.getCanonicalTagType(Record->getOriginalDecl());
}
break;
}
@@ -9296,11 +9307,11 @@ bool InitializationSequence::Diagnose(Sema &S,
// initialized.
CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(S.CurContext);
S.Diag(Kind.getLocation(), diag::err_uninitialized_member_in_ctor)
- << (Constructor->getInheritedConstructor() ? 2 :
- Constructor->isImplicit() ? 1 : 0)
- << S.Context.getTypeDeclType(Constructor->getParent())
- << /*const=*/1
- << Entity.getName();
+ << (Constructor->getInheritedConstructor() ? 2
+ : Constructor->isImplicit() ? 1
+ : 0)
+ << S.Context.getCanonicalTagType(Constructor->getParent())
+ << /*const=*/1 << Entity.getName();
S.Diag(Entity.getDecl()->getLocation(), diag::note_previous_decl)
<< Entity.getName();
} else if (const auto *VD = dyn_cast_if_present<VarDecl>(Entity.getDecl());
@@ -10153,7 +10164,7 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
auto *RD = cast<CXXRecordDecl>(Pattern->getTemplatedDecl());
if (!(RD->getDefinition() && RD->isAggregate()))
return;
- QualType Ty = Context.getRecordType(RD);
+ QualType Ty = Context.getCanonicalTagType(RD);
SmallVector<QualType, 8> ElementTypes;
InitListChecker CheckInitList(*this, Entity, ListInit, Ty, ElementTypes);
@@ -10293,8 +10304,8 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
case OR_No_Viable_Function: {
CXXRecordDecl *Primary =
cast<ClassTemplateDecl>(Template)->getTemplatedDecl();
- bool Complete =
- isCompleteType(Kind.getLocation(), Context.getTypeDeclType(Primary));
+ bool Complete = isCompleteType(Kind.getLocation(),
+ Context.getCanonicalTagType(Primary));
Candidates.NoteCandidates(
PartialDiagnosticAt(
Kind.getLocation(),
diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp
index 2c00616bc62d7..1f47cd20b0359 100644
--- a/clang/lib/Sema/SemaLambda.cpp
+++ b/clang/lib/Sema/SemaLambda.cpp
@@ -427,7 +427,7 @@ bool Sema::DiagnoseInvalidExplicitObjectParameterInLambda(
.getNonReferenceType()
.getUnqualifiedType()
.getDesugaredType(getASTContext());
- QualType LambdaType = getASTContext().getRecordType(RD);
+ CanQualType LambdaType = getASTContext().getCanonicalTagType(RD);
if (LambdaType == ExplicitObjectParameterType)
return false;
@@ -459,7 +459,7 @@ bool Sema::DiagnoseInvalidExplicitObjectParameterInLambda(
return true;
}
- if (Paths.isAmbiguous(LambdaType->getCanonicalTypeUnqualified())) {
+ if (Paths.isAmbiguous(LambdaType)) {
std::string PathsDisplay = getAmbiguousPathsDisplayString(Paths);
Diag(CallLoc, diag::err_explicit_object_lambda_ambiguous_base)
<< LambdaType << PathsDisplay;
@@ -644,7 +644,7 @@ static EnumDecl *findEnumForBlockReturn(Expr *E) {
// - it is an expression of that formal enum type.
if (const EnumType *ET = E->getType()->getAs<EnumType>()) {
- return ET->getDecl();
+ return ET->getOriginalDecl()->getDefinitionOrSelf();
}
// Otherwise, nope.
@@ -761,7 +761,7 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) {
assert(isa<BlockScopeInfo>(CSI));
const EnumDecl *ED = findCommonEnumForBlockReturns(CSI.Returns);
if (ED) {
- CSI.ReturnType = Context.getTypeDeclType(ED);
+ CSI.ReturnType = Context.getCanonicalTagType(ED);
adjustBlockReturnsToEnum(*this, CSI.Returns, CSI.ReturnType);
return;
}
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index aa7191d2814fe..9299500e430f3 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -562,9 +562,8 @@ void LookupResult::resolveKind() {
// no ambiguity if they all refer to the same type, so unique based on the
// canonical type.
if (const auto *TD = dyn_cast<TypeDecl>(D)) {
- QualType T = getSema().Context.getTypeDeclType(TD);
auto UniqueResult = UniqueTypes.insert(
- std::make_pair(getSema().Context.getCanonicalType(T), I));
+ std::make_pair(getSema().Context.getCanonicalTypeDeclType(TD), I));
if (!UniqueResult.second) {
// The type is not unique.
ExistingI = UniqueResult.first->second;
@@ -716,7 +715,7 @@ static QualType getOpenCLEnumType(Sema &S, llvm::StringRef Name) {
EnumDecl *Decl = Result.getAsSingle<EnumDecl>();
if (!Decl)
return diagOpenCLBuiltinTypeError(S, "enum", Name);
- return S.Context.getEnumType(Decl);
+ return S.Context.getCanonicalTagType(Decl);
}
/// Lookup an OpenCL typedef type.
@@ -729,7 +728,8 @@ static QualType getOpenCLTypedefType(Sema &S, llvm::StringRef Name) {
TypedefNameDecl *Decl = Result.getAsSingle<TypedefNameDecl>();
if (!Decl)
return diagOpenCLBuiltinTypeError(S, "typedef", Name);
- return S.Context.getTypedefType(Decl);
+ return S.Context.getTypedefType(ElaboratedTypeKeyword::None,
+ /*Qualifier=*/std::nullopt, Decl);
}
/// Get the QualType instances of the return type and arguments for an OpenCL
@@ -1000,7 +1000,7 @@ static void LookupPredefedObjCSuperType(Sema &Sema, Scope *S) {
Sema.LookupName(Result, S);
if (Result.getResultKind() == LookupResultKind::Found)
if (const TagDecl *TD = Result.getAsSingle<TagDecl>())
- Context.setObjCSuperType(Context.getTagDeclType(TD));
+ Context.setObjCSuperType(Context.getCanonicalTagType(TD));
}
void Sema::LookupNecessaryTypesForBuiltin(Scope *S, unsigned ID) {
@@ -2434,12 +2434,12 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
if (!R.getLookupName())
return false;
+#ifndef NDEBUG
// Make sure that the declaration context is complete.
- assert((!isa<TagDecl>(LookupCtx) ||
- LookupCtx->isDependentContext() ||
- cast<TagDecl>(LookupCtx)->isCompleteDefinition() ||
- cast<TagDecl>(LookupCtx)->isBeingDefined()) &&
- "Declaration context must already be complete!");
+ if (const auto *TD = dyn_cast<TagDecl>(LookupCtx);
+ TD && !TD->isDependentType() && TD->getDefinition() == nullptr)
+ llvm_unreachable("Declaration context must already be complete!");
+#endif
struct QualifiedLookupInScope {
bool oldVal;
@@ -2595,10 +2595,8 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
// C++ [class.member.lookup]p3:
// type declarations (including injected-class-names) are replaced by
// the types they designate
- if (const TypeDecl *TD = dyn_cast<TypeDecl>(ND->getUnderlyingDecl())) {
- QualType T = Context.getTypeDeclType(TD);
- return T.getCanonicalType().getAsOpaquePtr();
- }
+ if (const TypeDecl *TD = dyn_cast<TypeDecl>(ND->getUnderlyingDecl()))
+ return Context.getCanonicalTypeDeclType(TD).getAsOpaquePtr();
return ND->getUnderlyingDecl()->getCanonicalDecl();
}
@@ -2703,12 +2701,10 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
CXXScopeSpec &SS) {
- auto *NNS = SS.getScopeRep();
- if (NNS && NNS->getKind() == NestedNameSpecifier::Super)
- return LookupInSuper(R, NNS->getAsRecordDecl());
- else
-
- return LookupQualifiedName(R, LookupCtx);
+ NestedNameSpecifier Qualifier = SS.getScopeRep();
+ if (Qualifier.getKind() == NestedNameSpecifier::Kind::Super)
+ return LookupInSuper(R, Qualifier.getAsSuper());
+ return LookupQualifiedName(R, LookupCtx);
}
bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS,
@@ -2730,7 +2726,9 @@ bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS,
IsDependent = !DC && ObjectType->isDependentType();
assert(((!DC && ObjectType->isDependentType()) ||
!ObjectType->isIncompleteType() || !ObjectType->getAs<TagType>() ||
- ObjectType->castAs<TagType>()->isBeingDefined()) &&
+ ObjectType->castAs<TagType>()
+ ->getOriginalDecl()
+ ->isEntityBeingDefined()) &&
"Caller should have completed object type");
} else if (SS && SS->isNotEmpty()) {
// This nested-name-specifier occurs after another nested-name-specifier,
@@ -2743,9 +2741,9 @@ bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS,
// FIXME: '__super' lookup semantics could be implemented by a
// LookupResult::isSuperLookup flag which skips the initial search of
// the lookup context in LookupQualified.
- if (NestedNameSpecifier *NNS = SS->getScopeRep();
- NNS->getKind() == NestedNameSpecifier::Super)
- return LookupInSuper(R, NNS->getAsRecordDecl());
+ if (NestedNameSpecifier Qualifier = SS->getScopeRep();
+ Qualifier.getKind() == NestedNameSpecifier::Kind::Super)
+ return LookupInSuper(R, Qualifier.getAsSuper());
}
IsDependent = !DC && isDependentScopeSpecifier(*SS);
} else {
@@ -2771,10 +2769,12 @@ bool Sema::LookupInSuper(LookupResult &R, CXXRecordDecl *Class) {
// members of Class itself. That is, the naming class is Class, and the
// access includes the access of the base.
for (const auto &BaseSpec : Class->bases()) {
- CXXRecordDecl *RD = cast<CXXRecordDecl>(
- BaseSpec.getType()->castAs<RecordType>()->getDecl());
+ CXXRecordDecl *RD =
+ cast<CXXRecordDecl>(
+ BaseSpec.getType()->castAs<RecordType>()->getOriginalDecl())
+ ->getDefinitionOrSelf();
LookupResult Result(*this, R.getLookupNameInfo(), R.getLookupKind());
- Result.setBaseObjectType(Context.getRecordType(Class));
+ Result.setBaseObjectType(Context.getCanonicalTagType(Class));
LookupQualifiedName(Result, RD);
// Copy the lookup results into the target, merging the base's access into
@@ -3100,7 +3100,7 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
// Only recurse into base classes for complete types.
if (!Result.S.isCompleteType(Result.InstantiationLoc,
- Result.S.Context.getRecordType(Class)))
+ Result.S.Context.getCanonicalTagType(Class)))
return;
// Add direct and indirect base classes along with their associated
@@ -3122,7 +3122,8 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
// the classes and namespaces of known non-dependent arguments.
if (!BaseType)
continue;
- CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(BaseType->getDecl());
+ CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(BaseType->getOriginalDecl())
+ ->getDefinitionOrSelf();
if (Result.addClassTransitive(BaseDecl)) {
// Find the associated namespace for this base class.
DeclContext *BaseCtx = BaseDecl->getDeclContext();
@@ -3193,8 +3194,10 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) {
// Its associated namespaces are the innermost enclosing
// namespaces of its associated classes.
case Type::Record: {
+ // FIXME: This should use the original decl.
CXXRecordDecl *Class =
- cast<CXXRecordDecl>(cast<RecordType>(T)->getDecl());
+ cast<CXXRecordDecl>(cast<RecordType>(T)->getOriginalDecl())
+ ->getDefinitionOrSelf();
addAssociatedClassesAndNamespaces(Result, Class);
break;
}
@@ -3204,7 +3207,9 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) {
// If it is a class member, its associated class is the
// member’s class; else it has no associated class.
case Type::Enum: {
- EnumDecl *Enum = cast<EnumType>(T)->getDecl();
+ // FIXME: This should use the original decl.
+ EnumDecl *Enum =
+ cast<EnumType>(T)->getOriginalDecl()->getDefinitionOrSelf();
DeclContext *Ctx = Enum->getDeclContext();
if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx))
@@ -3437,7 +3442,7 @@ Sema::LookupSpecialMember(CXXRecordDecl *RD, CXXSpecialMemberKind SM,
// Prepare for overload resolution. Here we construct a synthetic argument
// if necessary and make sure that implicit functions are declared.
- CanQualType CanTy = Context.getCanonicalType(Context.getTagDeclType(RD));
+ CanQualType CanTy = Context.getCanonicalTagType(RD);
DeclarationName Name;
Expr *Arg = nullptr;
unsigned NumArgs;
@@ -3644,7 +3649,7 @@ DeclContext::lookup_result Sema::LookupConstructors(CXXRecordDecl *Class) {
});
}
- CanQualType T = Context.getCanonicalType(Context.getTypeDeclType(Class));
+ CanQualType T = Context.getCanonicalTagType(Class);
DeclarationName Name = Context.DeclarationNames.getCXXConstructorName(T);
return Class->lookup(Name);
}
@@ -4259,7 +4264,7 @@ class LookupVisibleHelper {
const auto *Record = BaseType->getAs<RecordType>();
if (!Record)
continue;
- RD = Record->getDecl();
+ RD = Record->getOriginalDecl()->getDefinitionOrSelf();
}
// FIXME: It would be nice to be able to determine whether referencing
@@ -4545,41 +4550,101 @@ static void checkCorrectionVisibility(Sema &SemaRef, TypoCorrection &TC) {
// the given NestedNameSpecifier (i.e. given a NestedNameSpecifier "foo::bar::",
// fill the vector with the IdentifierInfo pointers for "foo" and "bar").
static void getNestedNameSpecifierIdentifiers(
- NestedNameSpecifier *NNS,
- SmallVectorImpl<const IdentifierInfo*> &Identifiers) {
- if (NestedNameSpecifier *Prefix = NNS->getPrefix())
- getNestedNameSpecifierIdentifiers(Prefix, Identifiers);
- else
+ NestedNameSpecifier NNS,
+ SmallVectorImpl<const IdentifierInfo *> &Identifiers) {
+ switch (NNS.getKind()) {
+ case NestedNameSpecifier::Kind::Null:
Identifiers.clear();
+ return;
- const IdentifierInfo *II = nullptr;
-
- switch (NNS->getKind()) {
- case NestedNameSpecifier::Identifier:
- II = NNS->getAsIdentifier();
- break;
-
- case NestedNameSpecifier::Namespace:
- if (NNS->getAsNamespace()->isAnonymousNamespace())
+ case NestedNameSpecifier::Kind::Namespace: {
+ auto [Namespace, Prefix] = NNS.getAsNamespaceAndPrefix();
+ getNestedNameSpecifierIdentifiers(Prefix, Identifiers);
+ if (const auto *NS = dyn_cast<NamespaceDecl>(Namespace);
+ NS && NS->isAnonymousNamespace())
return;
- II = NNS->getAsNamespace()->getIdentifier();
- break;
-
- case NestedNameSpecifier::NamespaceAlias:
- II = NNS->getAsNamespaceAlias()->getIdentifier();
- break;
+ Identifiers.push_back(Namespace->getIdentifier());
+ return;
+ }
- case NestedNameSpecifier::TypeSpec:
- II = QualType(NNS->getAsType(), 0).getBaseTypeIdentifier();
+ case NestedNameSpecifier::Kind::Type: {
+ for (const Type *T = NNS.getAsType(); /**/; /**/) {
+ switch (T->getTypeClass()) {
+ case Type::DependentName: {
+ auto *DT = cast<DependentNameType>(T);
+ getNestedNameSpecifierIdentifiers(DT->getQualifier(), Identifiers);
+ Identifiers.push_back(DT->getIdentifier());
+ return;
+ }
+ case Type::TemplateSpecialization: {
+ TemplateName Name =
+ cast<TemplateSpecializationType>(T)->getTemplateName();
+ if (const QualifiedTemplateName *QTN =
+ Name.getAsAdjustedQualifiedTemplateName()) {
+ getNestedNameSpecifierIdentifiers(QTN->getQualifier(), Identifiers);
+ Name = QTN->getUnderlyingTemplate();
+ }
+ if (const auto *TD = Name.getAsTemplateDecl(/*IgnoreDeduced=*/true))
+ Identifiers.push_back(TD->getIdentifier());
+ return;
+ }
+ case Type::DependentTemplateSpecialization: {
+ const DependentTemplateStorage &S =
+ cast<DependentTemplateSpecializationType>(T)
+ ->getDependentTemplateName();
+ getNestedNameSpecifierIdentifiers(S.getQualifier(), Identifiers);
+ // FIXME: Should this dig into the Name as well?
+ // Identifiers.push_back(S.getName().getIdentifier());
+ return;
+ }
+ case Type::SubstTemplateTypeParm:
+ T = cast<SubstTemplateTypeParmType>(T)
+ ->getReplacementType()
+ .getTypePtr();
+ continue;
+ case Type::TemplateTypeParm:
+ Identifiers.push_back(cast<TemplateTypeParmType>(T)->getIdentifier());
+ return;
+ case Type::Decltype:
+ return;
+ case Type::Enum:
+ case Type::Record:
+ case Type::InjectedClassName: {
+ auto *TT = cast<TagType>(T);
+ getNestedNameSpecifierIdentifiers(TT->getQualifier(), Identifiers);
+ Identifiers.push_back(TT->getOriginalDecl()->getIdentifier());
+ return;
+ }
+ case Type::Typedef: {
+ auto *TT = cast<TypedefType>(T);
+ getNestedNameSpecifierIdentifiers(TT->getQualifier(), Identifiers);
+ Identifiers.push_back(TT->getDecl()->getIdentifier());
+ return;
+ }
+ case Type::Using: {
+ auto *TT = cast<UsingType>(T);
+ getNestedNameSpecifierIdentifiers(TT->getQualifier(), Identifiers);
+ Identifiers.push_back(TT->getDecl()->getIdentifier());
+ return;
+ }
+ case Type::UnresolvedUsing: {
+ auto *TT = cast<UnresolvedUsingType>(T);
+ getNestedNameSpecifierIdentifiers(TT->getQualifier(), Identifiers);
+ Identifiers.push_back(TT->getDecl()->getIdentifier());
+ return;
+ }
+ default:
+ Identifiers.push_back(QualType(T, 0).getBaseTypeIdentifier());
+ return;
+ }
+ }
break;
+ }
- case NestedNameSpecifier::Global:
- case NestedNameSpecifier::Super:
+ case NestedNameSpecifier::Kind::Global:
+ case NestedNameSpecifier::Kind::Super:
return;
}
-
- if (II)
- Identifiers.push_back(II);
}
void TypoCorrectionConsumer::FoundDecl(NamedDecl *ND, NamedDecl *Hiding,
@@ -4612,11 +4677,11 @@ void TypoCorrectionConsumer::FoundName(StringRef Name) {
void TypoCorrectionConsumer::addKeywordResult(StringRef Keyword) {
// Compute the edit distance between the typo and this keyword,
// and add the keyword to the list of results.
- addName(Keyword, nullptr, nullptr, true);
+ addName(Keyword, /*ND=*/nullptr, /*NNS=*/std::nullopt, /*isKeyword=*/true);
}
void TypoCorrectionConsumer::addName(StringRef Name, NamedDecl *ND,
- NestedNameSpecifier *NNS, bool isKeyword) {
+ NestedNameSpecifier NNS, bool isKeyword) {
// Use a simple length-based heuristic to determine the minimum possible
// edit distance. If the minimum isn't good enough, bail out early.
StringRef TypoStr = Typo->getName();
@@ -4708,10 +4773,10 @@ void TypoCorrectionConsumer::addNamespaces(
Namespaces.addNameSpecifier(KNPair.first);
bool SSIsTemplate = false;
- if (NestedNameSpecifier *NNS =
- (SS && SS->isValid()) ? SS->getScopeRep() : nullptr) {
- if (const Type *T = NNS->getAsType())
- SSIsTemplate = T->getTypeClass() == Type::TemplateSpecialization;
+ if (NestedNameSpecifier NNS = (SS ? SS->getScopeRep() : std::nullopt)) {
+ if (NNS.getKind() == NestedNameSpecifier::Kind::Type)
+ SSIsTemplate =
+ NNS.getAsType()->getTypeClass() == Type::TemplateSpecialization;
}
// Do not transform this into an iterator-based loop. The loop body can
// trigger the creation of further types (through lazy deserialization) and
@@ -4813,17 +4878,15 @@ void TypoCorrectionConsumer::performQualifiedLookups() {
for (const TypoCorrection &QR : QualifiedResults) {
for (const auto &NSI : Namespaces) {
DeclContext *Ctx = NSI.DeclCtx;
- const Type *NSType = NSI.NameSpecifier->getAsType();
+ CXXRecordDecl *NamingClass = NSI.NameSpecifier.getAsRecordDecl();
// If the current NestedNameSpecifier refers to a class and the
// current correction candidate is the name of that class, then skip
// it as it is unlikely a qualified version of the class' constructor
// is an appropriate correction.
- if (CXXRecordDecl *NSDecl = NSType ? NSType->getAsCXXRecordDecl() :
- nullptr) {
- if (NSDecl->getIdentifier() == QR.getCorrectionAsIdentifierInfo())
- continue;
- }
+ if (NamingClass &&
+ NamingClass->getIdentifier() == QR.getCorrectionAsIdentifierInfo())
+ continue;
TypoCorrection TC(QR);
TC.ClearCorrectionDecls();
@@ -4853,7 +4916,7 @@ void TypoCorrectionConsumer::performQualifiedLookups() {
std::string NewQualified = TC.getAsString(SemaRef.getLangOpts());
std::string OldQualified;
llvm::raw_string_ostream OldOStream(OldQualified);
- SS->getScopeRep()->print(OldOStream, SemaRef.getPrintingPolicy());
+ SS->getScopeRep().print(OldOStream, SemaRef.getPrintingPolicy());
OldOStream << Typo->getName();
// If correction candidate would be an identical written qualified
// identifier, then the existing CXXScopeSpec probably included a
@@ -4864,8 +4927,7 @@ void TypoCorrectionConsumer::performQualifiedLookups() {
for (LookupResult::iterator TRD = Result.begin(), TRDEnd = Result.end();
TRD != TRDEnd; ++TRD) {
if (SemaRef.CheckMemberAccess(TC.getCorrectionRange().getBegin(),
- NSType ? NSType->getAsCXXRecordDecl()
- : nullptr,
+ NamingClass,
TRD.getPair()) == Sema::AR_accessible)
TC.addCorrectionDecl(*TRD);
}
@@ -4889,10 +4951,10 @@ void TypoCorrectionConsumer::performQualifiedLookups() {
TypoCorrectionConsumer::NamespaceSpecifierSet::NamespaceSpecifierSet(
ASTContext &Context, DeclContext *CurContext, CXXScopeSpec *CurScopeSpec)
: Context(Context), CurContextChain(buildContextChain(CurContext)) {
- if (NestedNameSpecifier *NNS =
- CurScopeSpec ? CurScopeSpec->getScopeRep() : nullptr) {
+ if (NestedNameSpecifier NNS =
+ CurScopeSpec ? CurScopeSpec->getScopeRep() : std::nullopt) {
llvm::raw_string_ostream SpecifierOStream(CurNameSpecifier);
- NNS->print(SpecifierOStream, Context.getPrintingPolicy());
+ NNS.print(SpecifierOStream, Context.getPrintingPolicy());
getNestedNameSpecifierIdentifiers(NNS, CurNameSpecifierIdentifiers);
}
@@ -4906,7 +4968,7 @@ TypoCorrectionConsumer::NamespaceSpecifierSet::NamespaceSpecifierSet(
// Add the global context as a NestedNameSpecifier
SpecifierInfo SI = {cast<DeclContext>(Context.getTranslationUnitDecl()),
- NestedNameSpecifier::GlobalSpecifier(Context), 1};
+ NestedNameSpecifier::getGlobal(), 1};
DistanceMap[1].push_back(SI);
}
@@ -4926,14 +4988,16 @@ auto TypoCorrectionConsumer::NamespaceSpecifierSet::buildContextChain(
unsigned
TypoCorrectionConsumer::NamespaceSpecifierSet::buildNestedNameSpecifier(
- DeclContextList &DeclChain, NestedNameSpecifier *&NNS) {
+ DeclContextList &DeclChain, NestedNameSpecifier &NNS) {
unsigned NumSpecifiers = 0;
for (DeclContext *C : llvm::reverse(DeclChain)) {
if (auto *ND = dyn_cast_or_null<NamespaceDecl>(C)) {
- NNS = NestedNameSpecifier::Create(Context, NNS, ND);
+ NNS = NestedNameSpecifier(Context, ND, NNS);
++NumSpecifiers;
} else if (auto *RD = dyn_cast_or_null<RecordDecl>(C)) {
- NNS = NestedNameSpecifier::Create(Context, NNS, RD->getTypeForDecl());
+ QualType T = Context.getTagType(ElaboratedTypeKeyword::None, NNS, RD,
+ /*OwnsTag=*/false);
+ NNS = NestedNameSpecifier(T.getTypePtr());
++NumSpecifiers;
}
}
@@ -4942,7 +5006,7 @@ TypoCorrectionConsumer::NamespaceSpecifierSet::buildNestedNameSpecifier(
void TypoCorrectionConsumer::NamespaceSpecifierSet::addNameSpecifier(
DeclContext *Ctx) {
- NestedNameSpecifier *NNS = nullptr;
+ NestedNameSpecifier NNS = std::nullopt;
unsigned NumSpecifiers = 0;
DeclContextList NamespaceDeclChain(buildContextChain(Ctx));
DeclContextList FullNamespaceDeclChain(NamespaceDeclChain);
@@ -4960,7 +5024,7 @@ void TypoCorrectionConsumer::NamespaceSpecifierSet::addNameSpecifier(
// Add an explicit leading '::' specifier if needed.
if (NamespaceDeclChain.empty()) {
// Rebuild the NestedNameSpecifier as a globally-qualified specifier.
- NNS = NestedNameSpecifier::GlobalSpecifier(Context);
+ NNS = NestedNameSpecifier::getGlobal();
NumSpecifiers =
buildNestedNameSpecifier(FullNamespaceDeclChain, NNS);
} else if (NamedDecl *ND =
@@ -4972,12 +5036,12 @@ void TypoCorrectionConsumer::NamespaceSpecifierSet::addNameSpecifier(
llvm::raw_string_ostream SpecifierOStream(NewNameSpecifier);
SmallVector<const IdentifierInfo *, 4> NewNameSpecifierIdentifiers;
getNestedNameSpecifierIdentifiers(NNS, NewNameSpecifierIdentifiers);
- NNS->print(SpecifierOStream, Context.getPrintingPolicy());
+ NNS.print(SpecifierOStream, Context.getPrintingPolicy());
SameNameSpecifier = NewNameSpecifier == CurNameSpecifier;
}
if (SameNameSpecifier || llvm::is_contained(CurContextIdentifiers, Name)) {
// Rebuild the NestedNameSpecifier as a globally-qualified specifier.
- NNS = NestedNameSpecifier::GlobalSpecifier(Context);
+ NNS = NestedNameSpecifier::getGlobal();
NumSpecifiers =
buildNestedNameSpecifier(FullNamespaceDeclChain, NNS);
}
@@ -5463,7 +5527,7 @@ std::string TypoCorrection::getAsString(const LangOptions &LO) const {
if (CorrectionNameSpec) {
std::string tmpBuffer;
llvm::raw_string_ostream PrefixOStream(tmpBuffer);
- CorrectionNameSpec->print(PrefixOStream, PrintingPolicy(LO));
+ CorrectionNameSpec.print(PrefixOStream, PrintingPolicy(LO));
PrefixOStream << CorrectionName;
return PrefixOStream.str();
}
diff --git a/clang/lib/Sema/SemaObjC.cpp b/clang/lib/Sema/SemaObjC.cpp
index 0f39a9817ce7f..27951c9105411 100644
--- a/clang/lib/Sema/SemaObjC.cpp
+++ b/clang/lib/Sema/SemaObjC.cpp
@@ -1407,7 +1407,8 @@ SemaObjC::ObjCSubscriptKind SemaObjC::CheckSubscriptingKind(Expr *FromE) {
int NoIntegrals = 0, NoObjCIdPointers = 0;
SmallVector<CXXConversionDecl *, 4> ConversionDecls;
- for (NamedDecl *D : cast<CXXRecordDecl>(RecordTy->getDecl())
+ for (NamedDecl *D : cast<CXXRecordDecl>(RecordTy->getOriginalDecl())
+ ->getDefinitionOrSelf()
->getVisibleConversionFunctions()) {
if (CXXConversionDecl *Conversion =
dyn_cast<CXXConversionDecl>(D->getUnderlyingDecl())) {
@@ -1510,7 +1511,7 @@ bool SemaObjC::isCFStringType(QualType T) {
if (!RT)
return false;
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl();
if (RD->getTagKind() != TagTypeKind::Struct)
return false;
diff --git a/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp
index 9d5106805892a..3dbce070e0e18 100644
--- a/clang/lib/Sema/SemaObjCProperty.cpp
+++ b/clang/lib/Sema/SemaObjCProperty.cpp
@@ -1312,7 +1312,9 @@ Decl *SemaObjC::ActOnPropertyImplDecl(
}
if (!CompleteTypeErr) {
const RecordType *RecordTy = PropertyIvarType->getAs<RecordType>();
- if (RecordTy && RecordTy->getDecl()->hasFlexibleArrayMember()) {
+ if (RecordTy && RecordTy->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->hasFlexibleArrayMember()) {
Diag(PropertyIvarLoc, diag::err_synthesize_variable_sized_ivar)
<< PropertyIvarType;
CompleteTypeErr = true; // suppress later diagnostics about the ivar
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index a30acbe9a4bca..d3cd86e86f992 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -7358,7 +7358,9 @@ SemaOpenMP::checkOpenMPDeclareVariantFunction(SemaOpenMP::DeclGroupPtrTy DG,
Diag(SR.getBegin(), diag::err_omp_interop_type_not_found) << SR;
return std::nullopt;
}
- QualType InteropType = Context.getTypeDeclType(TD);
+ QualType InteropType =
+ Context.getTypeDeclType(ElaboratedTypeKeyword::None,
+ /*Qualifier=*/std::nullopt, TD);
if (PTy->isVariadic()) {
Diag(FD->getLocation(), diag::err_omp_append_args_with_varargs) << SR;
return std::nullopt;
@@ -7378,7 +7380,7 @@ SemaOpenMP::checkOpenMPDeclareVariantFunction(SemaOpenMP::DeclGroupPtrTy DG,
auto *Method = dyn_cast<CXXMethodDecl>(FD);
if (Method && !Method->isStatic()) {
FnPtrType = Context.getMemberPointerType(
- AdjustedFnType, /*Qualifier=*/nullptr, Method->getParent());
+ AdjustedFnType, /*Qualifier=*/std::nullopt, Method->getParent());
ExprResult ER;
{
// Build addr_of unary op to correctly handle type checks for member
@@ -18612,10 +18614,11 @@ buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range,
if (const auto *TyRec = Ty->getAs<RecordType>()) {
// Complete the type if it can be completed.
// If the type is neither complete nor being defined, bail out now.
- if (SemaRef.isCompleteType(Loc, Ty) || TyRec->isBeingDefined() ||
- TyRec->getDecl()->getDefinition()) {
+ bool IsComplete = SemaRef.isCompleteType(Loc, Ty);
+ RecordDecl *RD = TyRec->getOriginalDecl()->getDefinition();
+ if (IsComplete || RD) {
Lookup.clear();
- SemaRef.LookupQualifiedName(Lookup, TyRec->getDecl());
+ SemaRef.LookupQualifiedName(Lookup, RD);
if (Lookup.empty()) {
Lookups.emplace_back();
Lookups.back().append(Lookup.begin(), Lookup.end());
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 34f512b13d6a8..180071828a5be 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -370,7 +370,7 @@ NarrowingKind StandardConversionSequence::getNarrowingKind(
// the underlying type is narrowing. This only arises for expressions of
// the form 'Enum{init}'.
if (auto *ET = ToType->getAs<EnumType>())
- ToType = ET->getDecl()->getIntegerType();
+ ToType = ET->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
switch (Second) {
// 'bool' is an integral type; dispatch to the right place to handle it.
@@ -1063,7 +1063,8 @@ static bool shouldAddReversedEqEq(Sema &S, SourceLocation OpLoc,
return true;
LookupResult Members(S, NotEqOp, OpLoc,
Sema::LookupNameKind::LookupMemberName);
- S.LookupQualifiedName(Members, RHSRec->getDecl());
+ S.LookupQualifiedName(Members,
+ RHSRec->getOriginalDecl()->getDefinitionOrSelf());
Members.suppressAccessDiagnostics();
for (NamedDecl *Op : Members)
if (FunctionsCorrespond(S.Context, EqFD, Op->getAsFunction()))
@@ -1268,7 +1269,7 @@ OverloadKind Sema::CheckOverload(Scope *S, FunctionDecl *New,
//
// Exception: if the scope is dependent and this is not a class
// member, the using declaration can only introduce an enumerator.
- if (UUD->getQualifier()->isDependent() && !UUD->isCXXClassMember()) {
+ if (UUD->getQualifier().isDependent() && !UUD->isCXXClassMember()) {
Match = *I;
return OverloadKind::NonFunction;
}
@@ -1471,9 +1472,8 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, FunctionDecl *New,
if (OldMethod->isImplicitObjectMemberFunction() &&
OldMethod->getParent() != NewMethod->getParent()) {
- QualType ParentType =
- SemaRef.Context.getTypeDeclType(OldMethod->getParent())
- .getCanonicalType();
+ CanQualType ParentType =
+ SemaRef.Context.getCanonicalTagType(OldMethod->getParent());
if (ParentType.getTypePtr() != BS.Ty)
return false;
BS.Ty = DS.Ty;
@@ -2293,7 +2293,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
== UO_AddrOf &&
"Non-address-of operator on non-static member address");
FromType = S.Context.getMemberPointerType(
- FromType, /*Qualifier=*/nullptr, Method->getParent());
+ FromType, /*Qualifier=*/std::nullopt, Method->getParent());
} else if (isa<UnaryOperator>(From->IgnoreParens())) {
assert(cast<UnaryOperator>(From->IgnoreParens())->getOpcode() ==
UO_AddrOf &&
@@ -2602,10 +2602,12 @@ IsTransparentUnionStandardConversion(Sema &S, Expr* From,
bool CStyle) {
const RecordType *UT = ToType->getAsUnionType();
- if (!UT || !UT->getDecl()->hasAttr<TransparentUnionAttr>())
+ if (!UT)
return false;
// The field to initialize within the transparent union.
- RecordDecl *UD = UT->getDecl();
+ const RecordDecl *UD = UT->getOriginalDecl()->getDefinitionOrSelf();
+ if (!UD->hasAttr<TransparentUnionAttr>())
+ return false;
// It's compatible if the expression matches any of the fields.
for (const auto *it : UD->fields()) {
if (IsStandardConversion(S, From, it->getType(), InOverloadResolution, SCS,
@@ -2663,15 +2665,17 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) {
if (const EnumType *FromEnumType = FromType->getAs<EnumType>()) {
// C++0x 7.2p9: Note that this implicit enum to int conversion is not
// provided for a scoped enumeration.
- if (FromEnumType->getDecl()->isScoped())
+ const EnumDecl *FromED =
+ FromEnumType->getOriginalDecl()->getDefinitionOrSelf();
+ if (FromED->isScoped())
return false;
// We can perform an integral promotion to the underlying type of the enum,
// even if that's not the promoted type. Note that the check for promoting
// the underlying type is based on the type alone, and does not consider
// the bitfield-ness of the actual source expression.
- if (FromEnumType->getDecl()->isFixed()) {
- QualType Underlying = FromEnumType->getDecl()->getIntegerType();
+ if (FromED->isFixed()) {
+ QualType Underlying = FromED->getIntegerType();
return Context.hasSameUnqualifiedType(Underlying, ToType) ||
IsIntegralPromotion(nullptr, Underlying, ToType);
}
@@ -2679,8 +2683,7 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) {
// We have already pre-calculated the promotion type, so this is trivial.
if (ToType->isIntegerType() &&
isCompleteType(From->getBeginLoc(), FromType))
- return Context.hasSameUnqualifiedType(
- ToType, FromEnumType->getDecl()->getPromotionType());
+ return Context.hasSameUnqualifiedType(ToType, FromED->getPromotionType());
// C++ [conv.prom]p5:
// If the bit-field has an enumerated type, it is treated as any other
@@ -3347,12 +3350,12 @@ void Sema::HandleFunctionTypeMismatch(PartialDiagnostic &PDiag,
ToMember->getMostRecentCXXRecordDecl())) {
PDiag << ft_different_class;
if (ToMember->isSugared())
- PDiag << Context.getTypeDeclType(
+ PDiag << Context.getCanonicalTagType(
ToMember->getMostRecentCXXRecordDecl());
else
PDiag << ToMember->getQualifier();
if (FromMember->isSugared())
- PDiag << Context.getTypeDeclType(
+ PDiag << Context.getCanonicalTagType(
FromMember->getMostRecentCXXRecordDecl());
else
PDiag << FromMember->getQualifier();
@@ -3636,12 +3639,12 @@ Sema::MemberPointerConversionResult Sema::CheckMemberPointerConversion(
CXXRecordDecl *FromClass = FromPtrType->getMostRecentCXXRecordDecl(),
*ToClass = ToPtrType->getMostRecentCXXRecordDecl();
- auto DiagCls = [](PartialDiagnostic &PD, NestedNameSpecifier *Qual,
- const CXXRecordDecl *Cls) {
- if (declaresSameEntity(Qual->getAsRecordDecl(), Cls))
+ auto DiagCls = [&](PartialDiagnostic &PD, NestedNameSpecifier Qual,
+ const CXXRecordDecl *Cls) {
+ if (declaresSameEntity(Qual.getAsRecordDecl(), Cls))
PD << Qual;
else
- PD << QualType(Cls->getTypeForDecl(), 0);
+ PD << Context.getCanonicalTagType(Cls);
};
auto DiagFromTo = [&](PartialDiagnostic &PD) -> PartialDiagnostic & {
DiagCls(PD, FromPtrType->getQualifier(), FromClass);
@@ -3658,8 +3661,7 @@ Sema::MemberPointerConversionResult Sema::CheckMemberPointerConversion(
if (!IsDerivedFrom(OpRange.getBegin(), Derived, Base, Paths))
return MemberPointerConversionResult::NotDerived;
- if (Paths.isAmbiguous(
- Base->getTypeForDecl()->getCanonicalTypeUnqualified())) {
+ if (Paths.isAmbiguous(Context.getCanonicalTagType(Base))) {
PartialDiagnostic PD = PDiag(diag::err_ambiguous_memptr_conv);
PD << int(Direction);
DiagFromTo(PD) << getAmbiguousPathsDisplayString(Paths) << OpRange;
@@ -3687,8 +3689,8 @@ Sema::MemberPointerConversionResult Sema::CheckMemberPointerConversion(
? diag::err_upcast_to_inaccessible_base
: diag::err_downcast_from_inaccessible_base,
[&](PartialDiagnostic &PD) {
- NestedNameSpecifier *BaseQual = FromPtrType->getQualifier(),
- *DerivedQual = ToPtrType->getQualifier();
+ NestedNameSpecifier BaseQual = FromPtrType->getQualifier(),
+ DerivedQual = ToPtrType->getQualifier();
if (Direction == MemberPointerConversionDirection::Upcast)
std::swap(BaseQual, DerivedQual);
DiagCls(PD, DerivedQual, Derived);
@@ -3983,8 +3985,9 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
if (!S.isCompleteType(From->getExprLoc(), ToType)) {
// We're not going to find any constructors.
- } else if (CXXRecordDecl *ToRecordDecl
- = dyn_cast<CXXRecordDecl>(ToRecordType->getDecl())) {
+ } else if (auto *ToRecordDecl =
+ dyn_cast<CXXRecordDecl>(ToRecordType->getOriginalDecl())) {
+ ToRecordDecl = ToRecordDecl->getDefinitionOrSelf();
Expr **Args = &From;
unsigned NumArgs = 1;
@@ -4057,8 +4060,9 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
// No conversion functions from incomplete types.
} else if (const RecordType *FromRecordType =
From->getType()->getAs<RecordType>()) {
- if (CXXRecordDecl *FromRecordDecl
- = dyn_cast<CXXRecordDecl>(FromRecordType->getDecl())) {
+ if (auto *FromRecordDecl =
+ dyn_cast<CXXRecordDecl>(FromRecordType->getOriginalDecl())) {
+ FromRecordDecl = FromRecordDecl->getDefinitionOrSelf();
// Add all of the conversion functions as candidates.
const auto &Conversions = FromRecordDecl->getVisibleConversionFunctions();
for (auto I = Conversions.begin(), E = Conversions.end(); I != E; ++I) {
@@ -4509,7 +4513,8 @@ getFixedEnumPromtion(Sema &S, const StandardConversionSequence &SCS) {
if (!FromType->isEnumeralType())
return FixedEnumPromotion::None;
- EnumDecl *Enum = FromType->castAs<EnumType>()->getDecl();
+ EnumDecl *Enum =
+ FromType->castAs<EnumType>()->getOriginalDecl()->getDefinitionOrSelf();
if (!Enum->isFixed())
return FixedEnumPromotion::None;
@@ -5145,7 +5150,9 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS,
Expr *Init, QualType T2, bool AllowRvalues,
bool AllowExplicit) {
assert(T2->isRecordType() && "Can only find conversions of record types.");
- auto *T2RecordDecl = cast<CXXRecordDecl>(T2->castAs<RecordType>()->getDecl());
+ auto *T2RecordDecl =
+ cast<CXXRecordDecl>(T2->castAs<RecordType>()->getOriginalDecl())
+ ->getDefinitionOrSelf();
OverloadCandidateSet CandidateSet(
DeclLoc, OverloadCandidateSet::CSK_InitByUserDefinedConversion);
@@ -5934,7 +5941,7 @@ static ImplicitConversionSequence TryObjectArgumentInitialization(
assert(FromType->isRecordType());
- QualType ClassType = S.Context.getTypeDeclType(ActingContext);
+ CanQualType ClassType = S.Context.getCanonicalTagType(ActingContext);
// C++98 [class.dtor]p2:
// A destructor can be invoked for a const, volatile or const volatile
// object.
@@ -6055,7 +6062,7 @@ static ImplicitConversionSequence TryObjectArgumentInitialization(
/// the implicit object parameter for the given Method with the given
/// expression.
ExprResult Sema::PerformImplicitObjectArgumentInitialization(
- Expr *From, NestedNameSpecifier *Qualifier, NamedDecl *FoundDecl,
+ Expr *From, NestedNameSpecifier Qualifier, NamedDecl *FoundDecl,
CXXMethodDecl *Method) {
QualType FromRecordType, DestType;
QualType ImplicitParamRecordType = Method->getFunctionObjectParameterType();
@@ -6840,8 +6847,9 @@ ExprResult Sema::PerformContextualImplicitConversion(
UnresolvedSet<4>
ViableConversions; // These are *potentially* viable in C++1y.
UnresolvedSet<4> ExplicitConversions;
- const auto &Conversions =
- cast<CXXRecordDecl>(RecordTy->getDecl())->getVisibleConversionFunctions();
+ const auto &Conversions = cast<CXXRecordDecl>(RecordTy->getOriginalDecl())
+ ->getDefinitionOrSelf()
+ ->getVisibleConversionFunctions();
bool HadMultipleCandidates =
(std::distance(Conversions.begin(), Conversions.end()) > 1);
@@ -7160,7 +7168,8 @@ void Sema::AddOverloadCandidate(
// C++ [class.copy]p3:
// A member function template is never instantiated to perform the copy
// of a class object to an object of its class type.
- QualType ClassType = Context.getTypeDeclType(Constructor->getParent());
+ CanQualType ClassType =
+ Context.getCanonicalTagType(Constructor->getParent());
if (Args.size() == 1 && Constructor->isSpecializationCopyingObject() &&
(Context.hasSameUnqualifiedType(ClassType, Args[0]->getType()) ||
IsDerivedFrom(Args[0]->getBeginLoc(), Args[0]->getType(),
@@ -7181,8 +7190,8 @@ void Sema::AddOverloadCandidate(
if (Shadow && Args.size() == 1 && Constructor->getNumParams() >= 1 &&
Constructor->getParamDecl(0)->getType()->isReferenceType()) {
QualType P = Constructor->getParamDecl(0)->getType()->getPointeeType();
- QualType C = Context.getRecordType(Constructor->getParent());
- QualType D = Context.getRecordType(Shadow->getParent());
+ CanQualType C = Context.getCanonicalTagType(Constructor->getParent());
+ CanQualType D = Context.getCanonicalTagType(Shadow->getParent());
SourceLocation Loc = Args.front()->getExprLoc();
if ((Context.hasSameUnqualifiedType(P, C) || IsDerivedFrom(Loc, P, C)) &&
(Context.hasSameUnqualifiedType(D, P) || IsDerivedFrom(Loc, D, P))) {
@@ -7403,7 +7412,7 @@ static bool convertArgsForAvailabilityChecks(
"Shouldn't have `this` for ctors!");
assert(!Method->isStatic() && "Shouldn't have `this` for static methods!");
ExprResult R = S.PerformImplicitObjectArgumentInitialization(
- ThisArg, /*Qualifier=*/nullptr, Method, Method);
+ ThisArg, /*Qualifier=*/std::nullopt, Method, Method);
if (R.isInvalid())
return false;
ConvertedThis = R.get();
@@ -8137,29 +8146,24 @@ bool Sema::CheckNonDependentConversions(
ArgType = ArgType->getPointeeType();
}
- if (auto *RT = ParamType->getAs<RecordType>())
- if (auto *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
- RD && RD->hasDefinition()) {
- if (llvm::any_of(LookupConstructors(RD), [](NamedDecl *ND) {
- auto Info = getConstructorInfo(ND);
- if (!Info)
- return false;
- CXXConstructorDecl *Ctor = Info.Constructor;
- /// isConvertingConstructor takes copy/move constructors into
- /// account!
- return !Ctor->isCopyOrMoveConstructor() &&
- Ctor->isConvertingConstructor(
- /*AllowExplicit=*/true);
- }))
- return true;
- }
-
- if (auto *RT = ArgType->getAs<RecordType>())
- if (auto *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
- RD && RD->hasDefinition() &&
- !RD->getVisibleConversionFunctions().empty()) {
- return true;
- }
+ if (auto *RD = ParamType->getAsCXXRecordDecl();
+ RD && RD->hasDefinition() &&
+ llvm::any_of(LookupConstructors(RD), [](NamedDecl *ND) {
+ auto Info = getConstructorInfo(ND);
+ if (!Info)
+ return false;
+ CXXConstructorDecl *Ctor = Info.Constructor;
+ /// isConvertingConstructor takes copy/move constructors into
+ /// account!
+ return !Ctor->isCopyOrMoveConstructor() &&
+ Ctor->isConvertingConstructor(
+ /*AllowExplicit=*/true);
+ }))
+ return true;
+ if (auto *RD = ArgType->getAsCXXRecordDecl();
+ RD && RD->hasDefinition() &&
+ !RD->getVisibleConversionFunctions().empty())
+ return true;
return false;
};
@@ -8313,7 +8317,8 @@ void Sema::AddConversionCandidate(
if (const auto *FromPtrType = ObjectType->getAs<PointerType>())
ObjectType = FromPtrType->getPointeeType();
const auto *ConversionContext =
- cast<CXXRecordDecl>(ObjectType->castAs<RecordType>()->getDecl());
+ cast<CXXRecordDecl>(ObjectType->castAs<RecordType>()->getOriginalDecl())
+ ->getDefinitionOrSelf();
// C++23 [over.best.ics.general]
// However, if the target is [...]
@@ -8713,15 +8718,16 @@ void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op,
// qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
// the set of member candidates is empty.
if (const RecordType *T1Rec = T1->getAs<RecordType>()) {
+ bool IsComplete = isCompleteType(OpLoc, T1);
+ CXXRecordDecl *T1RD =
+ cast<CXXRecordDecl>(T1Rec->getOriginalDecl())->getDefinition();
// Complete the type if it can be completed.
- if (!isCompleteType(OpLoc, T1) && !T1Rec->isBeingDefined())
- return;
// If the type is neither complete nor being defined, bail out now.
- if (!T1Rec->getDecl()->getDefinition())
+ if (!T1RD || (!IsComplete && !T1RD->isBeingDefined()))
return;
LookupResult Operators(*this, OpName, OpLoc, LookupOrdinaryName);
- LookupQualifiedName(Operators, T1Rec->getDecl());
+ LookupQualifiedName(Operators, T1RD);
Operators.suppressAccessDiagnostics();
for (LookupResult::iterator Oper = Operators.begin(),
@@ -8986,8 +8992,8 @@ BuiltinCandidateTypeSet::AddMemberPointerWithMoreQualifiedTypeVariants(
if ((CVR | BaseCVR) != CVR) continue;
QualType QPointeeTy = Context.getCVRQualifiedType(PointeeTy, CVR);
- MemberPointerTypes.insert(
- Context.getMemberPointerType(QPointeeTy, /*Qualifier=*/nullptr, Cls));
+ MemberPointerTypes.insert(Context.getMemberPointerType(
+ QPointeeTy, /*Qualifier=*/std::nullopt, Cls));
}
return true;
@@ -9064,7 +9070,8 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty,
if (!SemaRef.isCompleteType(Loc, Ty))
return;
- CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl());
+ auto *ClassDecl =
+ cast<CXXRecordDecl>(TyRec->getOriginalDecl())->getDefinitionOrSelf();
for (NamedDecl *D : ClassDecl->getVisibleConversionFunctions()) {
if (isa<UsingShadowDecl>(D))
D = cast<UsingShadowDecl>(D)->getTargetDecl();
@@ -10176,7 +10183,7 @@ class BuiltinOperatorOverloadBuilder {
if (S.getLangOpts().CPlusPlus11) {
for (QualType EnumTy : CandidateTypes[ArgIdx].enumeration_types()) {
- if (!EnumTy->castAs<EnumType>()->getDecl()->isScoped())
+ if (!EnumTy->castAs<EnumType>()->getOriginalDecl()->isScoped())
continue;
if (!AddedTypes.insert(S.Context.getCanonicalType(EnumTy)).second)
@@ -10931,9 +10938,9 @@ bool clang::isBetterOverloadCandidate(
isa<CXXConversionDecl>(Cand1.Function) ? TPOC_Conversion
: TPOC_Call,
Cand1.ExplicitCallArguments,
- Obj1Context ? QualType(Obj1Context->getTypeForDecl(), 0)
+ Obj1Context ? S.Context.getCanonicalTagType(Obj1Context)
: QualType{},
- Obj2Context ? QualType(Obj2Context->getTypeForDecl(), 0)
+ Obj2Context ? S.Context.getCanonicalTagType(Obj2Context)
: QualType{},
Cand1.isReversed() ^ Cand2.isReversed(), PartialOverloading)) {
return BetterTemplate == Cand1.Function->getPrimaryTemplate();
@@ -14873,8 +14880,8 @@ ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl,
if (Method->isExplicitObjectMemberFunction())
Exp = InitializeExplicitObjectArgument(*this, E, Method);
else
- Exp = PerformImplicitObjectArgumentInitialization(E, /*Qualifier=*/nullptr,
- FoundDecl, Method);
+ Exp = PerformImplicitObjectArgumentInitialization(
+ E, /*Qualifier=*/std::nullopt, FoundDecl, Method);
if (Exp.isInvalid())
return true;
@@ -15035,7 +15042,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
InputInit = InitializeExplicitObjectArgument(*this, Input, Method);
else
InputInit = PerformImplicitObjectArgumentInitialization(
- Input, /*Qualifier=*/nullptr, Best->FoundDecl, Method);
+ Input, /*Qualifier=*/std::nullopt, Best->FoundDecl, Method);
if (InputInit.isInvalid())
return ExprError();
Base = Input = InputInit.get();
@@ -15418,7 +15425,7 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
ParamIdx = 1;
} else {
Arg0 = PerformImplicitObjectArgumentInitialization(
- Args[0], /*Qualifier=*/nullptr, Best->FoundDecl, Method);
+ Args[0], /*Qualifier=*/std::nullopt, Best->FoundDecl, Method);
}
Arg1 = PerformCopyInitialization(
InitializedEntity::InitializeParameter(
@@ -15888,7 +15895,7 @@ ExprResult Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
ArgExpr = Args;
} else {
ExprResult Arg0 = PerformImplicitObjectArgumentInitialization(
- Args[0], /*Qualifier=*/nullptr, Best->FoundDecl, Method);
+ Args[0], /*Qualifier=*/std::nullopt, Best->FoundDecl, Method);
if (Arg0.isInvalid())
return ExprError();
@@ -16084,7 +16091,7 @@ ExprResult Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
CXXMethodDecl *Method = nullptr;
bool HadMultipleCandidates = false;
DeclAccessPair FoundDecl = DeclAccessPair::make(nullptr, AS_public);
- NestedNameSpecifier *Qualifier = nullptr;
+ NestedNameSpecifier Qualifier = std::nullopt;
if (isa<MemberExpr>(NakedMemExpr)) {
MemExpr = cast<MemberExpr>(NakedMemExpr);
Method = cast<CXXMethodDecl>(MemExpr->getMemberDecl());
@@ -16356,7 +16363,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
const auto *Record = Object.get()->getType()->castAs<RecordType>();
LookupResult R(*this, OpName, LParenLoc, LookupOrdinaryName);
- LookupQualifiedName(R, Record->getDecl());
+ LookupQualifiedName(R, Record->getOriginalDecl()->getDefinitionOrSelf());
R.suppressAccessDiagnostics();
for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end();
@@ -16400,8 +16407,9 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
// functions for each conversion function declared in an
// accessible base class provided the function is not hidden
// within T by another intervening declaration.
- const auto &Conversions =
- cast<CXXRecordDecl>(Record->getDecl())->getVisibleConversionFunctions();
+ const auto &Conversions = cast<CXXRecordDecl>(Record->getOriginalDecl())
+ ->getDefinitionOrSelf()
+ ->getVisibleConversionFunctions();
for (auto I = Conversions.begin(), E = Conversions.end();
!IgnoreSurrogateFunctions && I != E; ++I) {
NamedDecl *D = *I;
@@ -16551,7 +16559,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
IsError |= PrepareExplicitObjectArgument(*this, Method, Obj, Args, NewArgs);
} else {
ExprResult ObjRes = PerformImplicitObjectArgumentInitialization(
- Object.get(), /*Qualifier=*/nullptr, Best->FoundDecl, Method);
+ Object.get(), /*Qualifier=*/std::nullopt, Best->FoundDecl, Method);
if (ObjRes.isInvalid())
IsError = true;
else
@@ -16622,7 +16630,10 @@ ExprResult Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base,
return ExprError();
LookupResult R(*this, OpName, OpLoc, LookupOrdinaryName);
- LookupQualifiedName(R, Base->getType()->castAs<RecordType>()->getDecl());
+ LookupQualifiedName(R, Base->getType()
+ ->castAs<RecordType>()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf());
R.suppressAccessDiagnostics();
for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end();
@@ -16696,7 +16707,7 @@ ExprResult Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base,
Base = R.get();
} else {
ExprResult BaseResult = PerformImplicitObjectArgumentInitialization(
- Base, /*Qualifier=*/nullptr, Best->FoundDecl, Method);
+ Base, /*Qualifier=*/std::nullopt, Best->FoundDecl, Method);
if (BaseResult.isInvalid())
return ExprError();
Base = BaseResult.get();
@@ -16950,7 +16961,7 @@ ExprResult Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
assert(isa<DeclRefExpr>(SubExpr.get()) &&
"fixed to something other than a decl ref");
- NestedNameSpecifier *Qualifier =
+ NestedNameSpecifier Qualifier =
cast<DeclRefExpr>(SubExpr.get())->getQualifier();
assert(Qualifier &&
"fixed to a member ref with no nested name qualifier");
diff --git a/clang/lib/Sema/SemaPPC.cpp b/clang/lib/Sema/SemaPPC.cpp
index d5c83aedb3008..7c82e540a9194 100644
--- a/clang/lib/Sema/SemaPPC.cpp
+++ b/clang/lib/Sema/SemaPPC.cpp
@@ -41,8 +41,10 @@ void SemaPPC::checkAIXMemberAlignment(SourceLocation Loc, const Expr *Arg) {
return;
QualType ArgType = Arg->getType();
- for (const FieldDecl *FD :
- ArgType->castAs<RecordType>()->getDecl()->fields()) {
+ for (const FieldDecl *FD : ArgType->castAs<RecordType>()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->fields()) {
if (const auto *AA = FD->getAttr<AlignedAttr>()) {
CharUnits Alignment = getASTContext().toCharUnitsFromBits(
AA->getAlignment(getASTContext()));
diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp
index 3e03cb4bd5f99..76b705e7ad4a2 100644
--- a/clang/lib/Sema/SemaSYCL.cpp
+++ b/clang/lib/Sema/SemaSYCL.cpp
@@ -221,7 +221,7 @@ static SourceLocation SourceLocationForUserDeclaredType(QualType QT) {
SourceLocation Loc;
const Type *T = QT->getUnqualifiedDesugaredType();
if (const TagType *TT = dyn_cast<TagType>(T))
- Loc = TT->getDecl()->getLocation();
+ Loc = TT->getOriginalDecl()->getLocation();
else if (const ObjCInterfaceType *ObjCIT = dyn_cast<ObjCInterfaceType>(T))
Loc = ObjCIT->getDecl()->getLocation();
return Loc;
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index 923a9e81fbd6a..b5a5082d6e844 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -801,7 +801,7 @@ bool Sema::checkMustTailAttr(const Stmt *St, const Attr &MTA) {
const auto *MPT =
CalleeBinOp->getRHS()->getType()->castAs<MemberPointerType>();
CalleeType.This =
- Context.getTypeDeclType(MPT->getMostRecentCXXRecordDecl());
+ Context.getCanonicalTagType(MPT->getMostRecentCXXRecordDecl());
CalleeType.Func = MPT->getPointeeType()->castAs<FunctionProtoType>();
CalleeType.MemberType = FuncType::ft_pointer_to_member;
} else if (isa<CXXPseudoDestructorExpr>(CalleeExpr)) {
@@ -1257,7 +1257,7 @@ static bool ShouldDiagnoseSwitchCaseNotInEnum(const Sema &S,
dyn_cast<DeclRefExpr>(CaseExpr->IgnoreParenImpCasts())) {
if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
QualType VarType = VD->getType();
- QualType EnumType = S.Context.getTypeDeclType(ED);
+ CanQualType EnumType = S.Context.getCanonicalTagType(ED);
if (VD->hasGlobalStorage() && VarType.isConstQualified() &&
S.Context.hasSameUnqualifiedType(EnumType, VarType))
return false;
@@ -1287,11 +1287,11 @@ static void checkEnumTypesInSwitchStmt(Sema &S, const Expr *Cond,
return;
// Ignore anonymous enums.
- if (!CondEnumType->getDecl()->getIdentifier() &&
- !CondEnumType->getDecl()->getTypedefNameForAnonDecl())
+ if (!CondEnumType->getOriginalDecl()->getIdentifier() &&
+ !CondEnumType->getOriginalDecl()->getTypedefNameForAnonDecl())
return;
- if (!CaseEnumType->getDecl()->getIdentifier() &&
- !CaseEnumType->getDecl()->getTypedefNameForAnonDecl())
+ if (!CaseEnumType->getOriginalDecl()->getIdentifier() &&
+ !CaseEnumType->getOriginalDecl()->getTypedefNameForAnonDecl())
return;
if (S.Context.hasSameUnqualifiedType(CondType, CaseType))
@@ -1604,9 +1604,11 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
// If switch has default case, then ignore it.
if (!CaseListIsErroneous && !CaseListIsIncomplete && !HasConstantCond &&
- ET && ET->getDecl()->isCompleteDefinition() &&
- !ET->getDecl()->enumerators().empty()) {
- const EnumDecl *ED = ET->getDecl();
+ ET) {
+ const EnumDecl *ED = ET->getOriginalDecl()->getDefinitionOrSelf();
+ if (!ED->isCompleteDefinition() || ED->enumerators().empty())
+ goto enum_out;
+
EnumValsTy EnumVals;
// Gather all enum values, set their type and sort them,
@@ -1719,6 +1721,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
if (!hasCasesNotInSwitch)
SS->setAllEnumCasesCovered();
}
+ enum_out:;
}
if (BodyStmt)
@@ -1748,7 +1751,7 @@ Sema::DiagnoseAssignmentEnum(QualType DstType, QualType SrcType,
if (SrcExpr->isTypeDependent() || SrcExpr->isValueDependent())
return;
- const EnumDecl *ED = ET->getDecl();
+ const EnumDecl *ED = ET->getOriginalDecl()->getDefinitionOrSelf();
if (!ED->isClosed())
return;
@@ -3708,7 +3711,7 @@ class LocalTypedefNameReferencer : public DynamicRecursiveASTVisitor {
Sema &S;
};
bool LocalTypedefNameReferencer::VisitRecordType(RecordType *RT) {
- auto *R = dyn_cast<CXXRecordDecl>(RT->getDecl());
+ auto *R = dyn_cast<CXXRecordDecl>(RT->getOriginalDecl());
if (!R || !R->isLocalClass() || !R->isLocalClass()->isExternallyVisible() ||
R->isDependentType())
return true;
@@ -3927,7 +3930,7 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp,
<< RetValExp->getSourceRange();
if (FD->hasAttr<CmseNSEntryAttr>() && RetValExp) {
if (const auto *RT = dyn_cast<RecordType>(FnRetType.getCanonicalType())) {
- if (RT->getDecl()->isOrContainsUnion())
+ if (RT->getOriginalDecl()->isOrContainsUnion())
Diag(RetValExp->getBeginLoc(), diag::warn_cmse_nonsecure_union) << 1;
}
}
@@ -4618,7 +4621,8 @@ void Sema::ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope,
// Build the context parameter
DeclContext *DC = CapturedDecl::castToDeclContext(CD);
IdentifierInfo *ParamName = &Context.Idents.get("__context");
- QualType ParamType = Context.getPointerType(Context.getTagDeclType(RD));
+ CanQualType ParamType =
+ Context.getPointerType(Context.getCanonicalTagType(RD));
auto *Param =
ImplicitParamDecl::Create(Context, DC, Loc, ParamName, ParamType,
ImplicitParamKind::CapturedContext);
@@ -4660,9 +4664,10 @@ void Sema::ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope,
assert(!ContextIsFound &&
"null type has been found already for '__context' parameter");
IdentifierInfo *ParamName = &Context.Idents.get("__context");
- QualType ParamType = Context.getPointerType(Context.getTagDeclType(RD))
- .withConst()
- .withRestrict();
+ QualType ParamType =
+ Context.getPointerType(Context.getCanonicalTagType(RD))
+ .withConst()
+ .withRestrict();
auto *Param =
ImplicitParamDecl::Create(Context, DC, Loc, ParamName, ParamType,
ImplicitParamKind::CapturedContext);
@@ -4682,7 +4687,8 @@ void Sema::ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope,
if (!ContextIsFound) {
// Add __context implicitly if it is not specified.
IdentifierInfo *ParamName = &Context.Idents.get("__context");
- QualType ParamType = Context.getPointerType(Context.getTagDeclType(RD));
+ CanQualType ParamType =
+ Context.getPointerType(Context.getCanonicalTagType(RD));
auto *Param =
ImplicitParamDecl::Create(Context, DC, Loc, ParamName, ParamType,
ImplicitParamKind::CapturedContext);
diff --git a/clang/lib/Sema/SemaStmtAsm.cpp b/clang/lib/Sema/SemaStmtAsm.cpp
index 4507a21a4c111..cd8b98c7444eb 100644
--- a/clang/lib/Sema/SemaStmtAsm.cpp
+++ b/clang/lib/Sema/SemaStmtAsm.cpp
@@ -894,7 +894,7 @@ bool Sema::LookupInlineAsmField(StringRef Base, StringRef Member,
QT = PT->getPointeeType();
RT = QT->getAs<RecordType>();
} else if (TypeDecl *TD = dyn_cast<TypeDecl>(FoundDecl))
- RT = TD->getTypeForDecl()->getAs<RecordType>();
+ RT = Context.getTypeDeclType(TD)->getAs<RecordType>();
else if (FieldDecl *TD = dyn_cast<FieldDecl>(FoundDecl))
RT = TD->getType()->getAs<RecordType>();
if (!RT)
@@ -907,7 +907,8 @@ bool Sema::LookupInlineAsmField(StringRef Base, StringRef Member,
LookupResult FieldResult(*this, &Context.Idents.get(NextMember),
SourceLocation(), LookupMemberName);
- if (!LookupQualifiedName(FieldResult, RT->getDecl()))
+ RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
+ if (!LookupQualifiedName(FieldResult, RD))
return true;
if (!FieldResult.isSingleResult())
@@ -919,7 +920,7 @@ bool Sema::LookupInlineAsmField(StringRef Base, StringRef Member,
if (!FD)
return true;
- const ASTRecordLayout &RL = Context.getASTRecordLayout(RT->getDecl());
+ const ASTRecordLayout &RL = Context.getASTRecordLayout(RD);
unsigned i = FD->getFieldIndex();
CharUnits Result = Context.toCharUnitsFromBits(RL.getFieldOffset(i));
Offset += (unsigned)Result.getQuantity();
@@ -951,7 +952,8 @@ Sema::LookupInlineAsmVarDeclField(Expr *E, StringRef Member,
LookupResult FieldResult(*this, &Context.Idents.get(Member), AsmLoc,
LookupMemberName);
- if (!LookupQualifiedName(FieldResult, RT->getDecl()))
+ if (!LookupQualifiedName(FieldResult,
+ RT->getOriginalDecl()->getDefinitionOrSelf()))
return ExprResult();
// Only normal and indirect field results will work.
diff --git a/clang/lib/Sema/SemaSwift.cpp b/clang/lib/Sema/SemaSwift.cpp
index 4000beff7dc49..a99222c5ed55f 100644
--- a/clang/lib/Sema/SemaSwift.cpp
+++ b/clang/lib/Sema/SemaSwift.cpp
@@ -130,7 +130,7 @@ static bool isErrorParameter(Sema &S, QualType QT) {
// Check for CFError**.
if (const auto *PT = Pointee->getAs<PointerType>())
if (const auto *RT = PT->getPointeeType()->getAs<RecordType>())
- if (S.ObjC().isCFError(RT->getDecl()))
+ if (S.ObjC().isCFError(RT->getOriginalDecl()->getDefinitionOrSelf()))
return true;
return false;
@@ -272,7 +272,8 @@ static void checkSwiftAsyncErrorBlock(Sema &S, Decl *D,
// Check for CFError *.
if (const auto *PtrTy = Param->getAs<PointerType>()) {
if (const auto *RT = PtrTy->getPointeeType()->getAs<RecordType>()) {
- if (S.ObjC().isCFError(RT->getDecl())) {
+ if (S.ObjC().isCFError(
+ RT->getOriginalDecl()->getDefinitionOrSelf())) {
AnyErrorParams = true;
break;
}
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 1a98b3583185e..d71594dc2ba8f 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -291,7 +291,7 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
FoundUsingShadow ? TemplateName(FoundUsingShadow) : TemplateName(TD);
assert(!FoundUsingShadow || FoundUsingShadow->getTargetDecl() == TD);
if (!SS.isInvalid()) {
- NestedNameSpecifier *Qualifier = SS.getScopeRep();
+ NestedNameSpecifier Qualifier = SS.getScopeRep();
Template = Context.getQualifiedTemplateName(Qualifier, hasTemplateKeyword,
Template);
}
@@ -363,9 +363,8 @@ bool Sema::DiagnoseUnknownTemplateName(const IdentifierInfo &II,
// The code is missing a 'template' keyword prior to the dependent template
// name.
- NestedNameSpecifier *Qualifier = (NestedNameSpecifier *)SS->getScopeRep();
SuggestedTemplate = TemplateTy::make(Context.getDependentTemplateName(
- {Qualifier, &II, /*HasTemplateKeyword=*/false}));
+ {SS->getScopeRep(), &II, /*HasTemplateKeyword=*/false}));
Diag(IILoc, diag::err_template_kw_missing)
<< SuggestedTemplate.get()
<< FixItHint::CreateInsertion(IILoc, "template ");
@@ -397,7 +396,9 @@ bool Sema::LookupTemplateName(LookupResult &Found, Scope *S, CXXScopeSpec &SS,
IsDependent = !LookupCtx && ObjectType->isDependentType();
assert((IsDependent || !ObjectType->isIncompleteType() ||
!ObjectType->getAs<TagType>() ||
- ObjectType->castAs<TagType>()->isBeingDefined()) &&
+ ObjectType->castAs<TagType>()
+ ->getOriginalDecl()
+ ->isEntityBeingDefined()) &&
"Caller should have completed object type");
// Template names cannot appear inside an Objective-C class or object type
@@ -797,9 +798,9 @@ bool Sema::DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation,
if (!Complain || (PatternDef && PatternDef->isInvalidDecl()))
return true;
- QualType InstantiationTy;
+ CanQualType InstantiationTy;
if (TagDecl *TD = dyn_cast<TagDecl>(Instantiation))
- InstantiationTy = Context.getTypeDeclType(TD);
+ InstantiationTy = Context.getCanonicalTagType(TD);
if (PatternDef) {
Diag(PointOfInstantiation,
diag::err_template_instantiate_within_definition)
@@ -907,7 +908,7 @@ static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef,
TypeSourceInfo *DI;
QualType T = SemaRef.GetTypeFromParser(Arg.getAsType(), &DI);
if (!DI)
- DI = SemaRef.Context.getTrivialTypeSourceInfo(T, Arg.getLocation());
+ DI = SemaRef.Context.getTrivialTypeSourceInfo(T, Arg.getNameLoc());
return TemplateArgumentLoc(TemplateArgument(T), DI);
}
@@ -924,9 +925,9 @@ static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef,
else
TArg = Template;
return TemplateArgumentLoc(
- SemaRef.Context, TArg,
+ SemaRef.Context, TArg, Arg.getTemplateKwLoc(),
Arg.getScopeSpec().getWithLocInContext(SemaRef.Context),
- Arg.getLocation(), Arg.getEllipsisLoc());
+ Arg.getNameLoc(), Arg.getEllipsisLoc());
}
}
@@ -967,15 +968,12 @@ ParsedTemplateArgument Sema::ActOnTemplateTypeArgument(TypeResult ParsedType) {
TL = PET.getPatternLoc();
}
- CXXScopeSpec SS;
- if (auto ET = TL.getAs<ElaboratedTypeLoc>()) {
- SS.Adopt(ET.getQualifierLoc());
- TL = ET.getNamedTypeLoc();
- }
-
if (auto DTST = TL.getAs<DeducedTemplateSpecializationTypeLoc>()) {
TemplateName Name = DTST.getTypePtr()->getTemplateName();
- ParsedTemplateArgument Result(SS, TemplateTy::make(Name),
+ CXXScopeSpec SS;
+ SS.Adopt(DTST.getQualifierLoc());
+ ParsedTemplateArgument Result(/*TemplateKwLoc=*/SourceLocation(), SS,
+ TemplateTy::make(Name),
DTST.getTemplateNameLoc());
if (EllipsisLoc.isValid())
Result = Result.getTemplatePackExpansion(EllipsisLoc);
@@ -2106,11 +2104,11 @@ DeclResult Sema::CheckClassTemplate(
bool ShouldAddRedecl =
!(TUK == TagUseKind::Friend && CurContext->isDependentContext());
- CXXRecordDecl *NewClass =
- CXXRecordDecl::Create(Context, Kind, SemanticContext, KWLoc, NameLoc, Name,
- PrevClassTemplate && ShouldAddRedecl ?
- PrevClassTemplate->getTemplatedDecl() : nullptr,
- /*DelayTypeCreation=*/true);
+ CXXRecordDecl *NewClass = CXXRecordDecl::Create(
+ Context, Kind, SemanticContext, KWLoc, NameLoc, Name,
+ PrevClassTemplate && ShouldAddRedecl
+ ? PrevClassTemplate->getTemplatedDecl()
+ : nullptr);
SetNestedNameSpecifier(*this, NewClass, SS);
if (NumOuterTemplateParamLists > 0)
NewClass->setTemplateParameterListsInfo(
@@ -2139,12 +2137,6 @@ DeclResult Sema::CheckClassTemplate(
if (ModulePrivateLoc.isValid())
NewTemplate->setModulePrivate();
- // Build the type for the class template declaration now.
- QualType T = NewTemplate->getInjectedClassNameSpecialization();
- T = Context.getInjectedClassNameType(NewClass, T);
- assert(T->isDependentType() && "Class template type is not dependent?");
- (void)T;
-
// If we are providing an explicit specialization of a member that is a
// class template, make a note of that.
if (PrevClassTemplate &&
@@ -2635,11 +2627,11 @@ struct DependencyChecker : DynamicRecursiveASTVisitor {
return DynamicRecursiveASTVisitor::TraverseStmt(S);
}
- bool TraverseTypeLoc(TypeLoc TL) override {
+ bool TraverseTypeLoc(TypeLoc TL, bool TraverseQualifier = true) override {
if (IgnoreNonTypeDependent && !TL.isNull() &&
!TL.getType()->isDependentType())
return true;
- return DynamicRecursiveASTVisitor::TraverseTypeLoc(TL);
+ return DynamicRecursiveASTVisitor::TraverseTypeLoc(TL, TraverseQualifier);
}
bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) override {
@@ -2676,8 +2668,12 @@ struct DependencyChecker : DynamicRecursiveASTVisitor {
return TraverseTemplateArgument(T->getArgumentPack());
}
- bool TraverseInjectedClassNameType(InjectedClassNameType *T) override {
- return TraverseType(T->getInjectedSpecializationType());
+ bool TraverseInjectedClassNameType(InjectedClassNameType *T,
+ bool TraverseQualifier) override {
+ // An InjectedClassNameType will never have a dependent template name,
+ // so no need to traverse it.
+ return TraverseTemplateArguments(
+ T->getTemplateArgs(T->getOriginalDecl()->getASTContext()));
}
};
} // end anonymous namespace
@@ -2700,14 +2696,14 @@ static SourceRange getRangeOfTypeInNestedNameSpecifier(ASTContext &Context,
QualType T,
const CXXScopeSpec &SS) {
NestedNameSpecifierLoc NNSLoc(SS.getScopeRep(), SS.location_data());
- while (NestedNameSpecifier *NNS = NNSLoc.getNestedNameSpecifier()) {
- if (const Type *CurType = NNS->getAsType()) {
- if (Context.hasSameUnqualifiedType(T, QualType(CurType, 0)))
- return NNSLoc.getTypeLoc().getSourceRange();
- } else
+ for (;;) {
+ NestedNameSpecifier NNS = NNSLoc.getNestedNameSpecifier();
+ if (NNS.getKind() != NestedNameSpecifier::Kind::Type)
break;
-
- NNSLoc = NNSLoc.getPrefix();
+ if (Context.hasSameUnqualifiedType(T, QualType(NNS.getAsType(), 0)))
+ return NNSLoc.castAsTypeLoc().getSourceRange();
+ // FIXME: This will always be empty.
+ NNSLoc = NNSLoc.getAsNamespaceAndPrefix().Prefix;
}
return SourceRange();
@@ -2726,12 +2722,13 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
// by the nested-name-specifier and walking out until we run out of types.
SmallVector<QualType, 4> NestedTypes;
QualType T;
- if (SS.getScopeRep()) {
- if (CXXRecordDecl *Record
- = dyn_cast_or_null<CXXRecordDecl>(computeDeclContext(SS, true)))
- T = Context.getTypeDeclType(Record);
+ if (NestedNameSpecifier Qualifier = SS.getScopeRep();
+ Qualifier.getKind() == NestedNameSpecifier::Kind::Type) {
+ if (CXXRecordDecl *Record =
+ dyn_cast_or_null<CXXRecordDecl>(computeDeclContext(SS, true)))
+ T = Context.getCanonicalTagType(Record);
else
- T = QualType(SS.getScopeRep()->getAsType(), 0);
+ T = QualType(Qualifier.getAsType(), 0);
}
// If we found an explicit specialization that prevents us from needing
@@ -2779,9 +2776,10 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
// Look one step prior in a dependent template specialization type.
if (const DependentTemplateSpecializationType *DependentTST
= T->getAs<DependentTemplateSpecializationType>()) {
- if (NestedNameSpecifier *NNS =
- DependentTST->getDependentTemplateName().getQualifier())
- T = QualType(NNS->getAsType(), 0);
+ if (NestedNameSpecifier NNS =
+ DependentTST->getDependentTemplateName().getQualifier();
+ NNS.getKind() == NestedNameSpecifier::Kind::Type)
+ T = QualType(NNS.getAsType(), 0);
else
T = QualType();
continue;
@@ -2789,8 +2787,9 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
// Look one step prior in a dependent name type.
if (const DependentNameType *DependentName = T->getAs<DependentNameType>()){
- if (NestedNameSpecifier *NNS = DependentName->getQualifier())
- T = QualType(NNS->getAsType(), 0);
+ if (NestedNameSpecifier NNS = DependentName->getQualifier();
+ NNS.getKind() == NestedNameSpecifier::Kind::Type)
+ T = QualType(NNS.getAsType(), 0);
else
T = QualType();
continue;
@@ -2800,7 +2799,7 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
if (const EnumType *EnumT = T->getAs<EnumType>()) {
// FIXME: Forward-declared enums require a TSK_ExplicitSpecialization
// check here.
- EnumDecl *Enum = EnumT->getDecl();
+ EnumDecl *Enum = EnumT->getOriginalDecl();
// Get to the parent type.
if (TypeDecl *Parent = dyn_cast<TypeDecl>(Enum->getParent()))
@@ -3100,7 +3099,8 @@ void Sema::NoteAllFoundTemplates(TemplateName Name) {
}
}
-static QualType builtinCommonTypeImpl(Sema &S, TemplateName BaseTemplate,
+static QualType builtinCommonTypeImpl(Sema &S, ElaboratedTypeKeyword Keyword,
+ TemplateName BaseTemplate,
SourceLocation TemplateLoc,
ArrayRef<TemplateArgument> Ts) {
auto lookUpCommonType = [&](TemplateArgument T1,
@@ -3108,7 +3108,8 @@ static QualType builtinCommonTypeImpl(Sema &S, TemplateName BaseTemplate,
// Don't bother looking for other specializations if both types are
// builtins - users aren't allowed to specialize for them
if (T1.getAsType()->isBuiltinType() && T2.getAsType()->isBuiltinType())
- return builtinCommonTypeImpl(S, BaseTemplate, TemplateLoc, {T1, T2});
+ return builtinCommonTypeImpl(S, Keyword, BaseTemplate, TemplateLoc,
+ {T1, T2});
TemplateArgumentListInfo Args;
Args.addArgument(TemplateArgumentLoc(
@@ -3122,7 +3123,7 @@ static QualType builtinCommonTypeImpl(Sema &S, TemplateName BaseTemplate,
Sema::ContextRAII TUContext(S, S.Context.getTranslationUnitDecl());
QualType BaseTemplateInst =
- S.CheckTemplateIdType(BaseTemplate, TemplateLoc, Args);
+ S.CheckTemplateIdType(Keyword, BaseTemplate, TemplateLoc, Args);
if (SFINAE.hasErrorOccurred())
return QualType();
@@ -3235,7 +3236,7 @@ static QualType builtinCommonTypeImpl(Sema &S, TemplateName BaseTemplate,
}
static bool isInVkNamespace(const RecordType *RT) {
- DeclContext *DC = RT->getDecl()->getDeclContext();
+ DeclContext *DC = RT->getOriginalDecl()->getDeclContext();
if (!DC)
return false;
@@ -3252,8 +3253,9 @@ static SpirvOperand checkHLSLSpirvTypeOperand(Sema &SemaRef,
if (auto *RT = OperandArg->getAs<RecordType>()) {
bool Literal = false;
SourceLocation LiteralLoc;
- if (isInVkNamespace(RT) && RT->getDecl()->getName() == "Literal") {
- auto SpecDecl = dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());
+ if (isInVkNamespace(RT) && RT->getOriginalDecl()->getName() == "Literal") {
+ auto SpecDecl =
+ dyn_cast<ClassTemplateSpecializationDecl>(RT->getOriginalDecl());
assert(SpecDecl);
const TemplateArgumentList &LiteralArgs = SpecDecl->getTemplateArgs();
@@ -3264,8 +3266,9 @@ static SpirvOperand checkHLSLSpirvTypeOperand(Sema &SemaRef,
}
if (RT && isInVkNamespace(RT) &&
- RT->getDecl()->getName() == "integral_constant") {
- auto SpecDecl = dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());
+ RT->getOriginalDecl()->getName() == "integral_constant") {
+ auto SpecDecl =
+ dyn_cast<ClassTemplateSpecializationDecl>(RT->getOriginalDecl());
assert(SpecDecl);
const TemplateArgumentList &ConstantArgs = SpecDecl->getTemplateArgs();
@@ -3287,11 +3290,10 @@ static SpirvOperand checkHLSLSpirvTypeOperand(Sema &SemaRef,
return SpirvOperand::createType(OperandArg);
}
-static QualType
-checkBuiltinTemplateIdType(Sema &SemaRef, BuiltinTemplateDecl *BTD,
- ArrayRef<TemplateArgument> Converted,
- SourceLocation TemplateLoc,
- TemplateArgumentListInfo &TemplateArgs) {
+static QualType checkBuiltinTemplateIdType(
+ Sema &SemaRef, ElaboratedTypeKeyword Keyword, BuiltinTemplateDecl *BTD,
+ ArrayRef<TemplateArgument> Converted, SourceLocation TemplateLoc,
+ TemplateArgumentListInfo &TemplateArgs) {
ASTContext &Context = SemaRef.getASTContext();
switch (BTD->getBuiltinTemplateKind()) {
@@ -3338,7 +3340,7 @@ checkBuiltinTemplateIdType(Sema &SemaRef, BuiltinTemplateDecl *BTD,
// The first template argument will be reused as the template decl that
// our synthetic template arguments will be applied to.
- return SemaRef.CheckTemplateIdType(Converted[0].getAsTemplate(),
+ return SemaRef.CheckTemplateIdType(Keyword, Converted[0].getAsTemplate(),
TemplateLoc, SyntheticTemplateArgs);
}
@@ -3375,14 +3377,16 @@ checkBuiltinTemplateIdType(Sema &SemaRef, BuiltinTemplateDecl *BTD,
TemplateName BaseTemplate = Converted[0].getAsTemplate();
ArrayRef<TemplateArgument> Ts = Converted[3].getPackAsArray();
- if (auto CT = builtinCommonTypeImpl(SemaRef, BaseTemplate, TemplateLoc, Ts);
+ if (auto CT = builtinCommonTypeImpl(SemaRef, Keyword, BaseTemplate,
+ TemplateLoc, Ts);
!CT.isNull()) {
TemplateArgumentListInfo TAs;
TAs.addArgument(TemplateArgumentLoc(
TemplateArgument(CT), SemaRef.Context.getTrivialTypeSourceInfo(
CT, TemplateArgs[1].getLocation())));
TemplateName HasTypeMember = Converted[1].getAsTemplate();
- return SemaRef.CheckTemplateIdType(HasTypeMember, TemplateLoc, TAs);
+ return SemaRef.CheckTemplateIdType(Keyword, HasTypeMember, TemplateLoc,
+ TAs);
}
QualType HasNoTypeMember = Converted[2].getAsType();
return HasNoTypeMember;
@@ -3494,7 +3498,7 @@ class FailedBooleanConditionPrinterHelper : public PrinterHelper {
if (DR && DR->getQualifier()) {
// If this is a qualified name, expand the template arguments in nested
// qualifiers.
- DR->getQualifier()->print(OS, Policy, true);
+ DR->getQualifier().print(OS, Policy, true);
// Then print the decl itself.
const ValueDecl *VD = DR->getDecl();
OS << VD->getName();
@@ -3559,7 +3563,8 @@ Sema::findFailedBooleanCondition(Expr *Cond) {
return { FailedCond, Description };
}
-QualType Sema::CheckTemplateIdType(TemplateName Name,
+QualType Sema::CheckTemplateIdType(ElaboratedTypeKeyword Keyword,
+ TemplateName Name,
SourceLocation TemplateLoc,
TemplateArgumentListInfo &TemplateArgs) {
// FIXME: 'getUnderlying' loses SubstTemplateTemplateParm nodes from alias
@@ -3610,6 +3615,18 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
} else if (TypeAliasTemplateDecl *AliasTemplate =
dyn_cast<TypeAliasTemplateDecl>(Template)) {
+ // C++0x [dcl.type.elab]p2:
+ // If the identifier resolves to a typedef-name or the simple-template-id
+ // resolves to an alias template specialization, the
+ // elaborated-type-specifier is ill-formed.
+ if (Keyword != ElaboratedTypeKeyword::None &&
+ Keyword != ElaboratedTypeKeyword::Typename) {
+ SemaRef.Diag(TemplateLoc, diag::err_tag_reference_non_tag)
+ << AliasTemplate << NonTagKind::TypeAliasTemplate
+ << KeywordHelpers::getTagTypeKindForKeyword(Keyword);
+ SemaRef.Diag(AliasTemplate->getLocation(), diag::note_declared_at);
+ }
+
// Find the canonical type for this type alias template specialization.
TypeAliasDecl *Pattern = AliasTemplate->getTemplatedDecl();
if (Pattern->isInvalidDecl())
@@ -3677,8 +3694,8 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
return QualType();
}
} else if (auto *BTD = dyn_cast<BuiltinTemplateDecl>(Template)) {
- CanonType = checkBuiltinTemplateIdType(*this, BTD, CTAI.SugaredConverted,
- TemplateLoc, TemplateArgs);
+ CanonType = checkBuiltinTemplateIdType(
+ *this, Keyword, BTD, CTAI.SugaredConverted, TemplateLoc, TemplateArgs);
} else if (Name.isDependent() ||
TemplateSpecializationType::anyDependentTemplateArguments(
TemplateArgs, CTAI.CanonicalConverted)) {
@@ -3717,16 +3734,15 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
// Fetch the injected class name type and check whether its
// injected type is equal to the type we just built.
- QualType ICNT = Context.getTypeDeclType(Record);
- QualType Injected = cast<InjectedClassNameType>(ICNT)
- ->getInjectedSpecializationType();
+ CanQualType ICNT = Context.getCanonicalTagType(Record);
+ CanQualType Injected =
+ cast<InjectedClassNameType>(ICNT)->getCanonicalInjectedTST();
- if (CanonType != Injected->getCanonicalTypeInternal())
+ if (CanonType != Injected)
continue;
// If so, the canonical type of this TST is the injected
// class name type of the record we just found.
- assert(ICNT.isCanonical());
CanonType = ICNT;
break;
}
@@ -3768,7 +3784,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
// Diagnose uses of this specialization.
(void)DiagnoseUseOfDecl(Decl, TemplateLoc);
- CanonType = Context.getTypeDeclType(Decl);
+ CanonType = Context.getCanonicalTagType(Decl);
assert(isa<RecordType>(CanonType) &&
"type of non-dependent specialization is not a RecordType");
} else {
@@ -3779,7 +3795,8 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
// specialization, which refers back to the class template
// specialization we created or found.
return Context.getTemplateSpecializationType(
- Name, TemplateArgs.arguments(), CTAI.CanonicalConverted, CanonType);
+ Keyword, Name, TemplateArgs.arguments(), CTAI.CanonicalConverted,
+ CanonType);
}
void Sema::ActOnUndeclaredTypeTemplateName(Scope *S, TemplateTy &ParsedName,
@@ -3827,7 +3844,7 @@ bool Sema::resolveAssumedTemplateNameAsType(Scope *S, TemplateName &Name,
diagnoseTypo(Corrected, PDiag(diag::err_no_template_suggest)
<< ATN->getDeclName());
Name = Context.getQualifiedTemplateName(
- /*NNS=*/nullptr, /*TemplateKeyword=*/false,
+ /*Qualifier=*/std::nullopt, /*TemplateKeyword=*/false,
TemplateName(Corrected.getCorrectionDeclAs<TemplateDecl>()));
return false;
}
@@ -3838,11 +3855,12 @@ bool Sema::resolveAssumedTemplateNameAsType(Scope *S, TemplateName &Name,
}
TypeResult Sema::ActOnTemplateIdType(
- Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
- TemplateTy TemplateD, const IdentifierInfo *TemplateII,
- SourceLocation TemplateIILoc, SourceLocation LAngleLoc,
- ASTTemplateArgsPtr TemplateArgsIn, SourceLocation RAngleLoc,
- bool IsCtorOrDtorName, bool IsClassName,
+ Scope *S, ElaboratedTypeKeyword ElaboratedKeyword,
+ SourceLocation ElaboratedKeywordLoc, CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc, TemplateTy TemplateD,
+ const IdentifierInfo *TemplateII, SourceLocation TemplateIILoc,
+ SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgsIn,
+ SourceLocation RAngleLoc, bool IsCtorOrDtorName, bool IsClassName,
ImplicitTypenameContext AllowImplicitTypename) {
if (SS.isInvalid())
return true;
@@ -3858,8 +3876,9 @@ TypeResult Sema::ActOnTemplateIdType(
// elaborated-type-specifier (7.1.5.3).
if (!LookupCtx && isDependentScopeSpecifier(SS)) {
// C++2a relaxes some of those restrictions in [temp.res]p5.
- NestedNameSpecifier *NNS =
- NestedNameSpecifier::Create(Context, SS.getScopeRep(), TemplateII);
+ QualType DNT = Context.getDependentNameType(ElaboratedTypeKeyword::None,
+ SS.getScopeRep(), TemplateII);
+ NestedNameSpecifier NNS(DNT.getTypePtr());
if (AllowImplicitTypename == ImplicitTypenameContext::Yes) {
auto DB = DiagCompat(SS.getBeginLoc(), diag_compat::implicit_typename)
<< NNS;
@@ -3903,12 +3922,12 @@ TypeResult Sema::ActOnTemplateIdType(
if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) {
assert(SS.getScopeRep() == DTN->getQualifier());
QualType T = Context.getDependentTemplateSpecializationType(
- ElaboratedTypeKeyword::None, *DTN, TemplateArgs.arguments());
+ ElaboratedKeyword, *DTN, TemplateArgs.arguments());
// Build type-source information.
TypeLocBuilder TLB;
DependentTemplateSpecializationTypeLoc SpecTL
= TLB.push<DependentTemplateSpecializationTypeLoc>(T);
- SpecTL.setElaboratedKeywordLoc(SourceLocation());
+ SpecTL.setElaboratedKeywordLoc(ElaboratedKeywordLoc);
SpecTL.setQualifierLoc(SS.getWithLocInContext(Context));
SpecTL.setTemplateKeywordLoc(TemplateKWLoc);
SpecTL.setTemplateNameLoc(TemplateIILoc);
@@ -3919,30 +3938,17 @@ TypeResult Sema::ActOnTemplateIdType(
return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T));
}
- QualType SpecTy = CheckTemplateIdType(Template, TemplateIILoc, TemplateArgs);
+ QualType SpecTy = CheckTemplateIdType(ElaboratedKeyword, Template,
+ TemplateIILoc, TemplateArgs);
if (SpecTy.isNull())
return true;
// Build type-source information.
TypeLocBuilder TLB;
- TemplateSpecializationTypeLoc SpecTL =
- TLB.push<TemplateSpecializationTypeLoc>(SpecTy);
- SpecTL.setTemplateKeywordLoc(TemplateKWLoc);
- SpecTL.setTemplateNameLoc(TemplateIILoc);
- SpecTL.setLAngleLoc(LAngleLoc);
- SpecTL.setRAngleLoc(RAngleLoc);
- for (unsigned i = 0, e = SpecTL.getNumArgs(); i != e; ++i)
- SpecTL.setArgLocInfo(i, TemplateArgs[i].getLocInfo());
-
- // Create an elaborated-type-specifier containing the nested-name-specifier.
- QualType ElTy =
- getElaboratedType(ElaboratedTypeKeyword::None,
- !IsCtorOrDtorName ? SS : CXXScopeSpec(), SpecTy);
- ElaboratedTypeLoc ElabTL = TLB.push<ElaboratedTypeLoc>(ElTy);
- ElabTL.setElaboratedKeywordLoc(SourceLocation());
- if (!ElabTL.isEmpty())
- ElabTL.setQualifierLoc(SS.getWithLocInContext(Context));
- return CreateParsedType(ElTy, TLB.getTypeSourceInfo(Context, ElTy));
+ TLB.push<TemplateSpecializationTypeLoc>(SpecTy).set(
+ ElaboratedKeywordLoc, SS.getWithLocInContext(Context), TemplateKWLoc,
+ TemplateIILoc, TemplateArgs);
+ return CreateParsedType(SpecTy, TLB.getTypeSourceInfo(Context, SpecTy));
}
TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK,
@@ -3989,24 +3995,14 @@ TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK,
return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T));
}
- if (TypeAliasTemplateDecl *TAT =
- dyn_cast_or_null<TypeAliasTemplateDecl>(Template.getAsTemplateDecl())) {
- // C++0x [dcl.type.elab]p2:
- // If the identifier resolves to a typedef-name or the simple-template-id
- // resolves to an alias template specialization, the
- // elaborated-type-specifier is ill-formed.
- Diag(TemplateLoc, diag::err_tag_reference_non_tag)
- << TAT << NonTagKind::TypeAliasTemplate << TagKind;
- Diag(TAT->getLocation(), diag::note_declared_at);
- }
-
- QualType Result = CheckTemplateIdType(Template, TemplateLoc, TemplateArgs);
+ QualType Result =
+ CheckTemplateIdType(Keyword, Template, TemplateLoc, TemplateArgs);
if (Result.isNull())
return TypeResult(true);
// Check the tag kind
if (const RecordType *RT = Result->getAs<RecordType>()) {
- RecordDecl *D = RT->getDecl();
+ RecordDecl *D = RT->getOriginalDecl()->getDefinitionOrSelf();
IdentifierInfo *Id = D->getIdentifier();
assert(Id && "templated class must have an identifier");
@@ -4022,21 +4018,9 @@ TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK,
// Provide source-location information for the template specialization.
TypeLocBuilder TLB;
- TemplateSpecializationTypeLoc SpecTL
- = TLB.push<TemplateSpecializationTypeLoc>(Result);
- SpecTL.setTemplateKeywordLoc(TemplateKWLoc);
- SpecTL.setTemplateNameLoc(TemplateLoc);
- SpecTL.setLAngleLoc(LAngleLoc);
- SpecTL.setRAngleLoc(RAngleLoc);
- for (unsigned i = 0, e = SpecTL.getNumArgs(); i != e; ++i)
- SpecTL.setArgLocInfo(i, TemplateArgs[i].getLocInfo());
-
- // Construct an elaborated type containing the nested-name-specifier (if any)
- // and tag keyword.
- Result = Context.getElaboratedType(Keyword, SS.getScopeRep(), Result);
- ElaboratedTypeLoc ElabTL = TLB.push<ElaboratedTypeLoc>(Result);
- ElabTL.setElaboratedKeywordLoc(TagLoc);
- ElabTL.setQualifierLoc(SS.getWithLocInContext(Context));
+ TLB.push<TemplateSpecializationTypeLoc>(Result).set(
+ TagLoc, SS.getWithLocInContext(Context), TemplateKWLoc, TemplateLoc,
+ TemplateArgs);
return CreateParsedType(Result, TLB.getTypeSourceInfo(Context, Result));
}
@@ -4958,7 +4942,7 @@ TemplateNameKind Sema::ActOnTemplateName(Scope *S,
return TNK_Non_template;
}
- NestedNameSpecifier *Qualifier = SS.getScopeRep();
+ NestedNameSpecifier Qualifier = SS.getScopeRep();
switch (Name.getKind()) {
case UnqualifiedIdKind::IK_Identifier:
@@ -5246,8 +5230,9 @@ static bool SubstDefaultTemplateArgument(
///
/// \returns the substituted template argument, or NULL if an error occurred.
static TemplateName SubstDefaultTemplateArgument(
- Sema &SemaRef, TemplateDecl *Template, SourceLocation TemplateLoc,
- SourceLocation RAngleLoc, TemplateTemplateParmDecl *Param,
+ Sema &SemaRef, TemplateDecl *Template, SourceLocation TemplateKWLoc,
+ SourceLocation TemplateLoc, SourceLocation RAngleLoc,
+ TemplateTemplateParmDecl *Param,
ArrayRef<TemplateArgument> SugaredConverted,
ArrayRef<TemplateArgument> CanonicalConverted,
NestedNameSpecifierLoc &QualifierLoc) {
@@ -5264,25 +5249,17 @@ static TemplateName SubstDefaultTemplateArgument(
TemplateArgLists.addOuterTemplateArguments(std::nullopt);
Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext());
- // Substitute into the nested-name-specifier first,
- QualifierLoc = Param->getDefaultArgument().getTemplateQualifierLoc();
- if (QualifierLoc) {
- QualifierLoc =
- SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, TemplateArgLists);
- if (!QualifierLoc)
- return TemplateName();
- }
- return SemaRef.SubstTemplateName(
- QualifierLoc,
- Param->getDefaultArgument().getArgument().getAsTemplate(),
- Param->getDefaultArgument().getTemplateNameLoc(),
- TemplateArgLists);
+ const TemplateArgumentLoc &A = Param->getDefaultArgument();
+ QualifierLoc = A.getTemplateQualifierLoc();
+ return SemaRef.SubstTemplateName(TemplateKWLoc, QualifierLoc,
+ A.getArgument().getAsTemplate(),
+ A.getTemplateNameLoc(), TemplateArgLists);
}
TemplateArgumentLoc Sema::SubstDefaultTemplateArgumentIfAvailable(
- TemplateDecl *Template, SourceLocation TemplateLoc,
- SourceLocation RAngleLoc, Decl *Param,
+ TemplateDecl *Template, SourceLocation TemplateKWLoc,
+ SourceLocation TemplateNameLoc, SourceLocation RAngleLoc, Decl *Param,
ArrayRef<TemplateArgument> SugaredConverted,
ArrayRef<TemplateArgument> CanonicalConverted, bool &HasDefaultArg) {
HasDefaultArg = false;
@@ -5293,8 +5270,8 @@ TemplateArgumentLoc Sema::SubstDefaultTemplateArgumentIfAvailable(
HasDefaultArg = true;
TemplateArgumentLoc Output;
- if (SubstDefaultTemplateArgument(*this, Template, TemplateLoc, RAngleLoc,
- TypeParm, SugaredConverted,
+ if (SubstDefaultTemplateArgument(*this, Template, TemplateNameLoc,
+ RAngleLoc, TypeParm, SugaredConverted,
CanonicalConverted, Output))
return TemplateArgumentLoc();
return Output;
@@ -5307,8 +5284,8 @@ TemplateArgumentLoc Sema::SubstDefaultTemplateArgumentIfAvailable(
HasDefaultArg = true;
TemplateArgumentLoc Output;
- if (SubstDefaultTemplateArgument(*this, Template, TemplateLoc, RAngleLoc,
- NonTypeParm, SugaredConverted,
+ if (SubstDefaultTemplateArgument(*this, Template, TemplateNameLoc,
+ RAngleLoc, NonTypeParm, SugaredConverted,
CanonicalConverted, Output))
return TemplateArgumentLoc();
return Output;
@@ -5320,17 +5297,16 @@ TemplateArgumentLoc Sema::SubstDefaultTemplateArgumentIfAvailable(
return TemplateArgumentLoc();
HasDefaultArg = true;
+ const TemplateArgumentLoc &A = TempTempParm->getDefaultArgument();
NestedNameSpecifierLoc QualifierLoc;
TemplateName TName = SubstDefaultTemplateArgument(
- *this, Template, TemplateLoc, RAngleLoc, TempTempParm, SugaredConverted,
- CanonicalConverted, QualifierLoc);
+ *this, Template, TemplateKWLoc, TemplateNameLoc, RAngleLoc, TempTempParm,
+ SugaredConverted, CanonicalConverted, QualifierLoc);
if (TName.isNull())
return TemplateArgumentLoc();
- return TemplateArgumentLoc(
- Context, TemplateArgument(TName),
- TempTempParm->getDefaultArgument().getTemplateQualifierLoc(),
- TempTempParm->getDefaultArgument().getTemplateNameLoc());
+ return TemplateArgumentLoc(Context, TemplateArgument(TName), TemplateKWLoc,
+ QualifierLoc, A.getTemplateNameLoc());
}
/// Convert a template-argument that we parsed as a type into a template, if
@@ -5338,33 +5314,24 @@ TemplateArgumentLoc Sema::SubstDefaultTemplateArgumentIfAvailable(
/// template template arguments and as template type arguments.
static TemplateArgumentLoc
convertTypeTemplateArgumentToTemplate(ASTContext &Context, TypeLoc TLoc) {
- // Extract and step over any surrounding nested-name-specifier.
- NestedNameSpecifierLoc QualLoc;
- if (auto ETLoc = TLoc.getAs<ElaboratedTypeLoc>()) {
- if (ETLoc.getTypePtr()->getKeyword() != ElaboratedTypeKeyword::None)
- return TemplateArgumentLoc();
+ auto TagLoc = TLoc.getAs<TagTypeLoc>();
+ if (!TagLoc)
+ return TemplateArgumentLoc();
- QualLoc = ETLoc.getQualifierLoc();
- TLoc = ETLoc.getNamedTypeLoc();
- }
// If this type was written as an injected-class-name, it can be used as a
// template template argument.
- if (auto InjLoc = TLoc.getAs<InjectedClassNameTypeLoc>())
- return TemplateArgumentLoc(Context, InjLoc.getTypePtr()->getTemplateName(),
- QualLoc, InjLoc.getNameLoc());
-
// If this type was written as an injected-class-name, it may have been
// converted to a RecordType during instantiation. If the RecordType is
// *not* wrapped in a TemplateSpecializationType and denotes a class
// template specialization, it must have come from an injected-class-name.
- if (auto RecLoc = TLoc.getAs<RecordTypeLoc>())
- if (auto *CTSD =
- dyn_cast<ClassTemplateSpecializationDecl>(RecLoc.getDecl()))
- return TemplateArgumentLoc(Context,
- TemplateName(CTSD->getSpecializedTemplate()),
- QualLoc, RecLoc.getNameLoc());
- return TemplateArgumentLoc();
+ TemplateName Name = TagLoc.getTypePtr()->getTemplateName(Context);
+ if (Name.isNull())
+ return TemplateArgumentLoc();
+
+ return TemplateArgumentLoc(Context, Name,
+ /*TemplateKWLoc=*/SourceLocation(),
+ TagLoc.getQualifierLoc(), TagLoc.getNameLoc());
}
bool Sema::CheckTemplateArgument(NamedDecl *Param, TemplateArgumentLoc &ArgLoc,
@@ -5897,8 +5864,8 @@ bool Sema::CheckTemplateArgumentList(
// (when the template parameter was part of a nested template) into
// the default argument.
TemplateArgumentLoc Arg = SubstDefaultTemplateArgumentIfAvailable(
- Template, TemplateLoc, RAngleLoc, *Param, CTAI.SugaredConverted,
- CTAI.CanonicalConverted, HasDefaultArg);
+ Template, /*TemplateKWLoc=*/SourceLocation(), TemplateLoc, RAngleLoc,
+ *Param, CTAI.SugaredConverted, CTAI.CanonicalConverted, HasDefaultArg);
if (Arg.getArgument().isNull()) {
if (!HasDefaultArg) {
@@ -6042,7 +6009,7 @@ namespace {
#include "clang/AST/TypeNodes.inc"
bool VisitTagDecl(const TagDecl *Tag);
- bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS);
+ bool VisitNestedNameSpecifier(NestedNameSpecifier NNS);
};
} // end anonymous namespace
@@ -6187,11 +6154,11 @@ bool UnnamedLocalNoLinkageFinder::VisitDeducedTemplateSpecializationType(
}
bool UnnamedLocalNoLinkageFinder::VisitRecordType(const RecordType* T) {
- return VisitTagDecl(T->getDecl());
+ return VisitTagDecl(T->getOriginalDecl()->getDefinitionOrSelf());
}
bool UnnamedLocalNoLinkageFinder::VisitEnumType(const EnumType* T) {
- return VisitTagDecl(T->getDecl());
+ return VisitTagDecl(T->getOriginalDecl()->getDefinitionOrSelf());
}
bool UnnamedLocalNoLinkageFinder::VisitTemplateTypeParmType(
@@ -6211,7 +6178,7 @@ bool UnnamedLocalNoLinkageFinder::VisitTemplateSpecializationType(
bool UnnamedLocalNoLinkageFinder::VisitInjectedClassNameType(
const InjectedClassNameType* T) {
- return VisitTagDecl(T->getDecl());
+ return VisitTagDecl(T->getOriginalDecl()->getDefinitionOrSelf());
}
bool UnnamedLocalNoLinkageFinder::VisitDependentNameType(
@@ -6221,10 +6188,7 @@ bool UnnamedLocalNoLinkageFinder::VisitDependentNameType(
bool UnnamedLocalNoLinkageFinder::VisitDependentTemplateSpecializationType(
const DependentTemplateSpecializationType* T) {
- if (auto *Q = T->getDependentTemplateName().getQualifier())
- return VisitNestedNameSpecifier(Q);
-
- return false;
+ return VisitNestedNameSpecifier(T->getDependentTemplateName().getQualifier());
}
bool UnnamedLocalNoLinkageFinder::VisitPackExpansionType(
@@ -6270,11 +6234,10 @@ bool UnnamedLocalNoLinkageFinder::VisitDependentBitIntType(
bool UnnamedLocalNoLinkageFinder::VisitTagDecl(const TagDecl *Tag) {
if (Tag->getDeclContext()->isFunctionOrMethod()) {
- S.Diag(SR.getBegin(),
- S.getLangOpts().CPlusPlus11 ?
- diag::warn_cxx98_compat_template_arg_local_type :
- diag::ext_template_arg_local_type)
- << S.Context.getTypeDeclType(Tag) << SR;
+ S.Diag(SR.getBegin(), S.getLangOpts().CPlusPlus11
+ ? diag::warn_cxx98_compat_template_arg_local_type
+ : diag::ext_template_arg_local_type)
+ << S.Context.getCanonicalTagType(Tag) << SR;
return true;
}
@@ -6291,21 +6254,15 @@ bool UnnamedLocalNoLinkageFinder::VisitTagDecl(const TagDecl *Tag) {
}
bool UnnamedLocalNoLinkageFinder::VisitNestedNameSpecifier(
- NestedNameSpecifier *NNS) {
- assert(NNS);
- if (NNS->getPrefix() && VisitNestedNameSpecifier(NNS->getPrefix()))
- return true;
-
- switch (NNS->getKind()) {
- case NestedNameSpecifier::Identifier:
- case NestedNameSpecifier::Namespace:
- case NestedNameSpecifier::NamespaceAlias:
- case NestedNameSpecifier::Global:
- case NestedNameSpecifier::Super:
+ NestedNameSpecifier NNS) {
+ switch (NNS.getKind()) {
+ case NestedNameSpecifier::Kind::Null:
+ case NestedNameSpecifier::Kind::Namespace:
+ case NestedNameSpecifier::Kind::Global:
+ case NestedNameSpecifier::Kind::Super:
return false;
-
- case NestedNameSpecifier::TypeSpec:
- return Visit(QualType(NNS->getAsType(), 0));
+ case NestedNameSpecifier::Kind::Type:
+ return Visit(QualType(NNS.getAsType(), 0));
}
llvm_unreachable("Invalid NestedNameSpecifier::Kind!");
}
@@ -7266,7 +7223,8 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// that case, this may extend the argument from 1 bit to 8 bits.
QualType IntegerType = ParamType;
if (const EnumType *Enum = IntegerType->getAs<EnumType>())
- IntegerType = Enum->getDecl()->getIntegerType();
+ IntegerType =
+ Enum->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
Value = Value.extOrTrunc(IntegerType->isBitIntType()
? Context.getIntWidth(IntegerType)
: Context.getTypeSize(IntegerType));
@@ -7364,7 +7322,8 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
QualType IntegerType = ParamType;
if (const EnumType *Enum = IntegerType->getAs<EnumType>()) {
- IntegerType = Enum->getDecl()->getIntegerType();
+ IntegerType =
+ Enum->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
}
if (ParamType->isBooleanType()) {
@@ -7727,10 +7686,9 @@ ExprResult Sema::BuildExpressionFromDeclTemplateArgument(
assert(VD->getDeclContext()->isRecord() &&
(isa<CXXMethodDecl>(VD) || isa<FieldDecl>(VD) ||
isa<IndirectFieldDecl>(VD)));
- QualType ClassType
- = Context.getTypeDeclType(cast<RecordDecl>(VD->getDeclContext()));
- NestedNameSpecifier *Qualifier =
- NestedNameSpecifier::Create(Context, nullptr, ClassType.getTypePtr());
+ CanQualType ClassType =
+ Context.getCanonicalTagType(cast<RecordDecl>(VD->getDeclContext()));
+ NestedNameSpecifier Qualifier(ClassType.getTypePtr());
SS.MakeTrivial(Context, Qualifier, Loc);
}
@@ -7822,7 +7780,7 @@ static Expr *BuildExpressionFromIntegralTemplateArgumentValue(
// type of literal for it.
QualType T = OrigT;
if (const EnumType *ET = OrigT->getAs<EnumType>())
- T = ET->getDecl()->getIntegerType();
+ T = ET->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
Expr *E;
if (T->isAnyCharacterType()) {
@@ -8691,7 +8649,6 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
isPartialSpecialization))
return true;
- QualType CanonType;
if (!isPartialSpecialization) {
// Create a new class template specialization declaration node for
// this explicit specialization or friend declaration.
@@ -8707,18 +8664,14 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
if (!PrevDecl)
ClassTemplate->AddSpecialization(Specialization, InsertPos);
-
- if (!CurContext->isDependentContext())
- CanonType = Context.getTypeDeclType(Specialization);
- }
-
- TypeSourceInfo *WrittenTy = Context.getTemplateSpecializationTypeInfo(
- Name, TemplateNameLoc, TemplateArgs, CTAI.CanonicalConverted, CanonType);
-
- if (isPartialSpecialization) {
+ } else {
+ CanQualType CanonType = CanQualType::CreateUnsafe(
+ Context.getCanonicalTemplateSpecializationType(
+ TemplateName(ClassTemplate->getCanonicalDecl()),
+ CTAI.CanonicalConverted));
if (Context.hasSameType(
- WrittenTy->getType(),
- ClassTemplate->getInjectedClassNameSpecialization()) &&
+ CanonType,
+ ClassTemplate->getCanonicalInjectedSpecializationType(Context)) &&
(!Context.getLangOpts().CPlusPlus20 ||
!TemplateParams->hasAssociatedConstraints())) {
// C++ [temp.class.spec]p9b3:
@@ -8740,13 +8693,12 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
}
// Create a new class template partial specialization declaration node.
- ClassTemplatePartialSpecializationDecl *PrevPartial
- = cast_or_null<ClassTemplatePartialSpecializationDecl>(PrevDecl);
+ ClassTemplatePartialSpecializationDecl *PrevPartial =
+ cast_or_null<ClassTemplatePartialSpecializationDecl>(PrevDecl);
ClassTemplatePartialSpecializationDecl *Partial =
ClassTemplatePartialSpecializationDecl::Create(
Context, Kind, DC, KWLoc, TemplateNameLoc, TemplateParams,
- ClassTemplate, CTAI.CanonicalConverted, WrittenTy->getType(),
- PrevPartial);
+ ClassTemplate, CTAI.CanonicalConverted, CanonType, PrevPartial);
Partial->setTemplateArgsAsWritten(TemplateArgs);
SetNestedNameSpecifier(*this, Partial, SS);
if (TemplateParameterLists.size() > 1 && SS.isSet()) {
@@ -8785,7 +8737,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
if (!Okay) {
SourceRange Range(TemplateNameLoc, RAngleLoc);
Diag(TemplateNameLoc, diag::err_specialization_after_instantiation)
- << Context.getTypeDeclType(Specialization) << Range;
+ << Context.getCanonicalTagType(Specialization) << Range;
Diag(PrevDecl->getPointOfInstantiation(),
diag::note_instantiation_required_here)
@@ -8848,6 +8800,13 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
Specialization->startDefinition();
if (TUK == TagUseKind::Friend) {
+ CanQualType CanonType = Context.getCanonicalTagType(Specialization);
+ TypeSourceInfo *WrittenTy = Context.getTemplateSpecializationTypeInfo(
+ ElaboratedTypeKeyword::None, /*ElaboratedKeywordLoc=*/SourceLocation(),
+ SS.getWithLocInContext(Context),
+ /*TemplateKeywordLoc=*/SourceLocation(), Name, TemplateNameLoc,
+ TemplateArgs, CTAI.CanonicalConverted, CanonType);
+
// Build the fully-sugared type for this class template
// specialization as the user wrote in the specialization
// itself. This means that we'll pretty-print the type retrieved
@@ -9884,9 +9843,6 @@ static bool CheckExplicitInstantiation(Sema &S, NamedDecl *D,
/// Determine whether the given scope specifier has a template-id in it.
static bool ScopeSpecifierHasTemplateId(const CXXScopeSpec &SS) {
- if (!SS.isSet())
- return false;
-
// C++11 [temp.explicit]p3:
// If the explicit instantiation is for a member function, a member class
// or a static data member of a class template specialization, the name of
@@ -9894,12 +9850,14 @@ static bool ScopeSpecifierHasTemplateId(const CXXScopeSpec &SS) {
// name shall be a simple-template-id.
//
// C++98 has the same restriction, just worded differently.
- for (NestedNameSpecifier *NNS = SS.getScopeRep(); NNS;
- NNS = NNS->getPrefix())
- if (const Type *T = NNS->getAsType())
- if (isa<TemplateSpecializationType>(T))
- return true;
-
+ for (NestedNameSpecifier NNS = SS.getScopeRep();
+ NNS.getKind() == NestedNameSpecifier::Kind::Type;
+ /**/) {
+ const Type *T = NNS.getAsType();
+ if (isa<TemplateSpecializationType>(T))
+ return true;
+ NNS = T->getPrefix();
+ }
return false;
}
@@ -10254,7 +10212,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc,
CXXRecordDecl *Pattern = Record->getInstantiatedFromMemberClass();
if (!Pattern) {
Diag(TemplateLoc, diag::err_explicit_instantiation_nontemplate_type)
- << Context.getTypeDeclType(Record);
+ << Context.getCanonicalTagType(Record);
Diag(Record->getLocation(), diag::note_nontemplate_decl_here);
return true;
}
@@ -10801,7 +10759,7 @@ TypeResult Sema::ActOnDependentTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// This has to hold, because SS is expected to be defined.
assert(Name && "Expected a name in a dependent tag");
- NestedNameSpecifier *NNS = SS.getScopeRep();
+ NestedNameSpecifier NNS = SS.getScopeRep();
if (!NNS)
return true;
@@ -10913,7 +10871,10 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
return CreateParsedType(T, Builder.getTypeSourceInfo(Context, T));
}
- QualType T = CheckTemplateIdType(Template, TemplateIILoc, TemplateArgs);
+ QualType T = CheckTemplateIdType(TypenameLoc.isValid()
+ ? ElaboratedTypeKeyword::Typename
+ : ElaboratedTypeKeyword::None,
+ Template, TemplateIILoc, TemplateArgs);
if (T.isNull())
return true;
@@ -10921,18 +10882,8 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
TypeLocBuilder Builder;
TemplateSpecializationTypeLoc SpecTL
= Builder.push<TemplateSpecializationTypeLoc>(T);
- SpecTL.setTemplateKeywordLoc(TemplateKWLoc);
- SpecTL.setTemplateNameLoc(TemplateIILoc);
- SpecTL.setLAngleLoc(LAngleLoc);
- SpecTL.setRAngleLoc(RAngleLoc);
- for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
- SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
-
- T = Context.getElaboratedType(Keyword, SS.getScopeRep(), T);
- ElaboratedTypeLoc TL = Builder.push<ElaboratedTypeLoc>(T);
- TL.setElaboratedKeywordLoc(TypenameLoc);
- TL.setQualifierLoc(SS.getWithLocInContext(Context));
-
+ SpecTL.set(TypenameLoc, SS.getWithLocInContext(Context), TemplateKWLoc,
+ TemplateIILoc, TemplateArgs);
TypeSourceInfo *TSI = Builder.getTypeSourceInfo(Context, T);
return CreateParsedType(T, TSI);
}
@@ -10946,11 +10897,12 @@ static bool isEnableIf(NestedNameSpecifierLoc NNS, const IdentifierInfo &II,
return false;
// ... within an explicitly-written template specialization...
- if (!NNS || !NNS.getNestedNameSpecifier()->getAsType())
+ if (NNS.getNestedNameSpecifier().getKind() != NestedNameSpecifier::Kind::Type)
return false;
- TypeLoc EnableIfTy = NNS.getTypeLoc();
- TemplateSpecializationTypeLoc EnableIfTSTLoc =
- EnableIfTy.getAs<TemplateSpecializationTypeLoc>();
+
+ // FIXME: Look through sugar.
+ auto EnableIfTSTLoc =
+ NNS.castAsTypeLoc().getAs<TemplateSpecializationTypeLoc>();
if (!EnableIfTSTLoc || EnableIfTSTLoc.getNumArgs() == 0)
return false;
const TemplateSpecializationType *EnableIfTST = EnableIfTSTLoc.getTypePtr();
@@ -10998,19 +10950,33 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
if (T.isNull())
return QualType();
- *TSI = Context.CreateTypeSourceInfo(T);
+ TypeLocBuilder TLB;
if (isa<DependentNameType>(T)) {
- DependentNameTypeLoc TL =
- (*TSI)->getTypeLoc().castAs<DependentNameTypeLoc>();
+ auto TL = TLB.push<DependentNameTypeLoc>(T);
TL.setElaboratedKeywordLoc(KeywordLoc);
TL.setQualifierLoc(QualifierLoc);
TL.setNameLoc(IILoc);
- } else {
- ElaboratedTypeLoc TL = (*TSI)->getTypeLoc().castAs<ElaboratedTypeLoc>();
+ } else if (isa<DeducedTemplateSpecializationType>(T)) {
+ auto TL = TLB.push<DeducedTemplateSpecializationTypeLoc>(T);
+ TL.setElaboratedKWLoc(KeywordLoc);
+ TL.setQualifierLoc(QualifierLoc);
+ TL.setNameLoc(IILoc);
+ } else if (isa<TemplateTypeParmType>(T)) {
+ // FIXME: There might be a 'typename' keyword here, but we just drop it
+ // as it can't be represented.
+ assert(!QualifierLoc);
+ TLB.pushTypeSpec(T).setNameLoc(IILoc);
+ } else if (isa<TagType>(T)) {
+ auto TL = TLB.push<TagTypeLoc>(T);
TL.setElaboratedKeywordLoc(KeywordLoc);
TL.setQualifierLoc(QualifierLoc);
- TL.getNamedTypeLoc().castAs<TypeSpecTypeLoc>().setNameLoc(IILoc);
+ TL.setNameLoc(IILoc);
+ } else if (isa<TypedefType>(T)) {
+ TLB.push<TypedefTypeLoc>(T).set(KeywordLoc, QualifierLoc, IILoc);
+ } else {
+ TLB.push<UnresolvedUsingTypeLoc>(T).set(KeywordLoc, QualifierLoc, IILoc);
}
+ *TSI = TLB.getTypeSourceInfo(Context, T);
return T;
}
@@ -11033,7 +10999,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
if (!Ctx) {
// If the nested-name-specifier is dependent and couldn't be
// resolved to a type, build a typename type.
- assert(QualifierLoc.getNestedNameSpecifier()->isDependent());
+ assert(QualifierLoc.getNestedNameSpecifier().isDependent());
return Context.getDependentNameType(Keyword,
QualifierLoc.getNestedNameSpecifier(),
&II);
@@ -11115,6 +11081,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
&II);
case LookupResultKind::Found:
+ // FXIME: Missing support for UsingShadowDecl on this path?
if (TypeDecl *Type = dyn_cast<TypeDecl>(Result.getFoundDecl())) {
// C++ [class.qual]p2:
// In a lookup in which function names are not ignored and the
@@ -11130,15 +11097,20 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
//
// FIXME: That's not strictly true: mem-initializer-id lookup does not
// ignore functions, but that appears to be an oversight.
- QualType T = getTypeDeclType(Ctx,
- Keyword == ElaboratedTypeKeyword::Typename
- ? DiagCtorKind::Typename
- : DiagCtorKind::None,
- Type, IILoc);
- // We found a type. Build an ElaboratedType, since the
- // typename-specifier was just sugar.
- return Context.getElaboratedType(
- Keyword, QualifierLoc.getNestedNameSpecifier(), T);
+ checkTypeDeclType(Ctx,
+ Keyword == ElaboratedTypeKeyword::Typename
+ ? DiagCtorKind::Typename
+ : DiagCtorKind::None,
+ Type, IILoc);
+ // FIXME: This appears to be the only case where a template type parameter
+ // can have an elaborated keyword. We should preserve it somehow.
+ if (isa<TemplateTypeParmDecl>(Type)) {
+ assert(Keyword == ElaboratedTypeKeyword::Typename);
+ assert(!QualifierLoc);
+ Keyword = ElaboratedTypeKeyword::None;
+ }
+ return Context.getTypeDeclType(
+ Keyword, QualifierLoc.getNestedNameSpecifier(), Type);
}
// C++ [dcl.type.simple]p2:
@@ -11148,22 +11120,22 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
if (getLangOpts().CPlusPlus17) {
if (auto *TD = getAsTypeTemplateDecl(Result.getFoundDecl())) {
if (!DeducedTSTContext) {
- QualType T(QualifierLoc
- ? QualifierLoc.getNestedNameSpecifier()->getAsType()
- : nullptr, 0);
- if (!T.isNull())
+ NestedNameSpecifier Qualifier = QualifierLoc.getNestedNameSpecifier();
+ if (Qualifier.getKind() == NestedNameSpecifier::Kind::Type)
Diag(IILoc, diag::err_dependent_deduced_tst)
- << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)) << T;
+ << (int)getTemplateNameKindForDiagnostics(TemplateName(TD))
+ << QualType(Qualifier.getAsType(), 0);
else
Diag(IILoc, diag::err_deduced_tst)
<< (int)getTemplateNameKindForDiagnostics(TemplateName(TD));
NoteTemplateLocation(*TD);
return QualType();
}
- return Context.getElaboratedType(
- Keyword, QualifierLoc.getNestedNameSpecifier(),
- Context.getDeducedTemplateSpecializationType(TemplateName(TD),
- QualType(), false));
+ TemplateName Name = Context.getQualifiedTemplateName(
+ QualifierLoc.getNestedNameSpecifier(), /*TemplateKeyword=*/false,
+ TemplateName(TD));
+ return Context.getDeducedTemplateSpecializationType(
+ Keyword, Name, /*DeducedType=*/QualType(), /*IsDependent=*/false);
}
}
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 94edd553aacd7..cebe2203a8407 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -613,38 +613,29 @@ DeduceTemplateSpecArguments(Sema &S, TemplateParameterList *TemplateParams,
TemplateDeductionInfo &Info, bool PartialOrdering,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
bool *HasDeducedAnyParam) {
- QualType UP = P;
- if (const auto *IP = P->getAs<InjectedClassNameType>())
- UP = IP->getInjectedSpecializationType();
-
- assert(isa<TemplateSpecializationType>(UP.getCanonicalType()));
- const TemplateSpecializationType *TP = ::getLastTemplateSpecType(UP);
- TemplateName TNP = TP->getTemplateName();
+ TemplateName TNP;
+ ArrayRef<TemplateArgument> PResolved;
+ if (isa<TemplateSpecializationType>(P.getCanonicalType())) {
+ const TemplateSpecializationType *TP = ::getLastTemplateSpecType(P);
+ TNP = TP->getTemplateName();
+ // FIXME: To preserve sugar, the TST needs to carry sugared resolved
+ // arguments.
+ PResolved = TP->getCanonicalTypeInternal()
+ ->castAs<TemplateSpecializationType>()
+ ->template_arguments();
+ } else {
+ const auto *TT = P->castAs<InjectedClassNameType>();
+ TNP = TT->getTemplateName(S.Context);
+ PResolved = TT->getTemplateArgs(S.Context);
+ }
// If the parameter is an alias template, there is nothing to deduce.
if (const auto *TD = TNP.getAsTemplateDecl(); TD && TD->isTypeAlias())
return TemplateDeductionResult::Success;
- // FIXME: To preserve sugar, the TST needs to carry sugared resolved
- // arguments.
- ArrayRef<TemplateArgument> PResolved =
- TP->getCanonicalTypeInternal()
- ->castAs<TemplateSpecializationType>()
- ->template_arguments();
-
- QualType UA = A;
- std::optional<NestedNameSpecifier *> NNS;
- // Treat an injected-class-name as its underlying template-id.
- if (const auto *Elaborated = A->getAs<ElaboratedType>()) {
- NNS = Elaborated->getQualifier();
- } else if (const auto *Injected = A->getAs<InjectedClassNameType>()) {
- UA = Injected->getInjectedSpecializationType();
- NNS = nullptr;
- }
-
// Check whether the template argument is a dependent template-id.
- if (isa<TemplateSpecializationType>(UA.getCanonicalType())) {
- const TemplateSpecializationType *SA = ::getLastTemplateSpecType(UA);
+ if (isa<TemplateSpecializationType>(A.getCanonicalType())) {
+ const TemplateSpecializationType *SA = ::getLastTemplateSpecType(A);
TemplateName TNA = SA->getTemplateName();
// If the argument is an alias template, there is nothing to deduce.
@@ -678,34 +669,36 @@ DeduceTemplateSpecArguments(Sema &S, TemplateParameterList *TemplateParams,
// If the argument type is a class template specialization, we
// perform template argument deduction using its template
// arguments.
- const auto *RA = UA->getAs<RecordType>();
- const auto *SA =
- RA ? dyn_cast<ClassTemplateSpecializationDecl>(RA->getDecl()) : nullptr;
- if (!SA) {
+ const auto *TA = A->getAs<TagType>();
+ TemplateName TNA;
+ if (TA) {
+ // FIXME: Can't use the template arguments from this TST, as they are not
+ // resolved.
+ if (const auto *TST = A->getAsNonAliasTemplateSpecializationType())
+ TNA = TST->getTemplateName();
+ else
+ TNA = TA->getTemplateName(S.Context);
+ }
+ if (TNA.isNull()) {
Info.FirstArg = TemplateArgument(P);
Info.SecondArg = TemplateArgument(A);
return TemplateDeductionResult::NonDeducedMismatch;
}
- TemplateName TNA = TemplateName(SA->getSpecializedTemplate());
- if (NNS)
- TNA = S.Context.getQualifiedTemplateName(
- *NNS, false, TemplateName(SA->getSpecializedTemplate()));
-
+ ArrayRef<TemplateArgument> AResolved = TA->getTemplateArgs(S.Context);
// Perform template argument deduction for the template name.
- if (auto Result = DeduceTemplateArguments(
- S, TemplateParams, TNP, TNA, Info,
- /*DefaultArguments=*/SA->getTemplateArgs().asArray(), PartialOrdering,
- Deduced, HasDeducedAnyParam);
+ if (auto Result =
+ DeduceTemplateArguments(S, TemplateParams, TNP, TNA, Info,
+ /*DefaultArguments=*/AResolved,
+ PartialOrdering, Deduced, HasDeducedAnyParam);
Result != TemplateDeductionResult::Success)
return Result;
// Perform template argument deduction for the template arguments.
- return DeduceTemplateArguments(S, TemplateParams, PResolved,
- SA->getTemplateArgs().asArray(), Info, Deduced,
- /*NumberOfArgumentsMustMatch=*/true,
- PartialOrdering, PackFold::ParameterToArgument,
- HasDeducedAnyParam);
+ return DeduceTemplateArguments(
+ S, TemplateParams, PResolved, AResolved, Info, Deduced,
+ /*NumberOfArgumentsMustMatch=*/true, PartialOrdering,
+ PackFold::ParameterToArgument, HasDeducedAnyParam);
}
static bool IsPossiblyOpaquelyQualifiedTypeInternal(const Type *T) {
@@ -2110,26 +2103,19 @@ static TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch(
Result != TemplateDeductionResult::Success)
return Result;
- QualType TP;
- if (MPP->isSugared()) {
- TP = S.Context.getTypeDeclType(MPP->getMostRecentCXXRecordDecl());
- } else {
- NestedNameSpecifier *QP = MPP->getQualifier();
- if (QP->getKind() == NestedNameSpecifier::Identifier)
- // Skip translation if it's a non-deduced context anyway.
- return TemplateDeductionResult::Success;
- TP = QualType(QP->translateToType(S.Context), 0);
- }
+ QualType TP =
+ MPP->isSugared()
+ ? S.Context.getCanonicalTagType(MPP->getMostRecentCXXRecordDecl())
+ : QualType(MPP->getQualifier().getAsType(), 0);
assert(!TP.isNull() && "member pointer with non-type class");
- QualType TA;
- if (MPA->isSugared()) {
- TA = S.Context.getTypeDeclType(MPA->getMostRecentCXXRecordDecl());
- } else {
- NestedNameSpecifier *QA = MPA->getQualifier();
- TA = QualType(QA->translateToType(S.Context), 0).getUnqualifiedType();
- }
+ QualType TA =
+ MPA->isSugared()
+ ? S.Context.getCanonicalTagType(MPA->getMostRecentCXXRecordDecl())
+ : QualType(MPA->getQualifier().getAsType(), 0)
+ .getUnqualifiedType();
assert(!TA.isNull() && "member pointer with non-type class");
+
return DeduceTemplateArgumentsByTypeMatch(
S, TemplateParams, TP, TA, Info, Deduced, SubTDF,
degradeCallPartialOrderingKind(POK),
@@ -2853,13 +2839,11 @@ Sema::getTrivialTemplateArgumentLoc(const TemplateArgument &Arg,
else if (QualifiedTemplateName *QTN =
Template.getAsQualifiedTemplateName())
Builder.MakeTrivial(Context, QTN->getQualifier(), Loc);
-
- if (Arg.getKind() == TemplateArgument::Template)
- return TemplateArgumentLoc(Context, Arg,
- Builder.getWithLocInContext(Context), Loc);
-
return TemplateArgumentLoc(
- Context, Arg, Builder.getWithLocInContext(Context), Loc, Loc);
+ Context, Arg, Loc, Builder.getWithLocInContext(Context), Loc,
+ /*EllipsisLoc=*/Arg.getKind() == TemplateArgument::TemplateExpansion
+ ? Loc
+ : SourceLocation());
}
case TemplateArgument::Expression:
@@ -3077,8 +3061,9 @@ static TemplateDeductionResult ConvertDeducedTemplateArguments(
S.getLangOpts().CPlusPlus17);
DefArg = S.SubstDefaultTemplateArgumentIfAvailable(
- TD, TD->getLocation(), TD->getSourceRange().getEnd(), Param,
- CTAI.SugaredConverted, CTAI.CanonicalConverted, HasDefaultArg);
+ TD, /*TemplateKWLoc=*/SourceLocation(), TD->getLocation(),
+ TD->getSourceRange().getEnd(), Param, CTAI.SugaredConverted,
+ CTAI.CanonicalConverted, HasDefaultArg);
}
// If there was no default argument, deduction is incomplete.
@@ -3437,7 +3422,7 @@ Sema::DeduceTemplateArgumentsFromType(TemplateDecl *TD, QualType FromType,
QualType PType;
if (const auto *CTD = dyn_cast<ClassTemplateDecl>(TD)) {
// Use the InjectedClassNameType.
- PType = Context.getTypeDeclType(CTD->getTemplatedDecl());
+ PType = Context.getCanonicalTagType(CTD->getTemplatedDecl());
} else if (const auto *AliasTemplate = dyn_cast<TypeAliasTemplateDecl>(TD)) {
PType = AliasTemplate->getTemplatedDecl()->getUnderlyingType();
} else {
@@ -4103,7 +4088,7 @@ static QualType GetTypeOfFunction(Sema &S, const OverloadExpr::FindResult &R,
return {};
return S.Context.getMemberPointerType(
- Fn->getType(), /*Qualifier=*/nullptr, Method->getParent());
+ Fn->getType(), /*Qualifier=*/std::nullopt, Method->getParent());
}
if (!R.IsAddressOfOperand) return Fn->getType();
@@ -5058,10 +5043,12 @@ namespace {
return TransformDesugared(TLB, TL);
QualType Result = SemaRef.Context.getDeducedTemplateSpecializationType(
- TL.getTypePtr()->getTemplateName(),
+ TL.getTypePtr()->getKeyword(), TL.getTypePtr()->getTemplateName(),
Replacement, Replacement.isNull());
auto NewTL = TLB.push<DeducedTemplateSpecializationTypeLoc>(Result);
+ NewTL.setElaboratedKWLoc(TL.getElaboratedKWLoc());
NewTL.setNameLoc(TL.getNameLoc());
+ NewTL.setQualifierLoc(TL.getQualifierLoc());
return Result;
}
@@ -6376,8 +6363,8 @@ Sema::getMoreSpecializedPartialSpecialization(
ClassTemplatePartialSpecializationDecl *PS1,
ClassTemplatePartialSpecializationDecl *PS2,
SourceLocation Loc) {
- QualType PT1 = PS1->getInjectedSpecializationType().getCanonicalType();
- QualType PT2 = PS2->getInjectedSpecializationType().getCanonicalType();
+ QualType PT1 = PS1->getCanonicalInjectedSpecializationType(Context);
+ QualType PT2 = PS2->getCanonicalInjectedSpecializationType(Context);
TemplateDeductionInfo Info(Loc);
return getMoreSpecialized(*this, PT1, PT2, PS1, PS2, Info);
@@ -6386,9 +6373,8 @@ Sema::getMoreSpecializedPartialSpecialization(
bool Sema::isMoreSpecializedThanPrimary(
ClassTemplatePartialSpecializationDecl *Spec, TemplateDeductionInfo &Info) {
ClassTemplateDecl *Primary = Spec->getSpecializedTemplate();
- QualType PrimaryT =
- Primary->getInjectedClassNameSpecialization().getCanonicalType();
- QualType PartialT = Spec->getInjectedSpecializationType().getCanonicalType();
+ QualType PrimaryT = Primary->getCanonicalInjectedSpecializationType(Context);
+ QualType PartialT = Spec->getCanonicalInjectedSpecializationType(Context);
ClassTemplatePartialSpecializationDecl *MaybeSpec =
getMoreSpecialized(*this, PartialT, PrimaryT, Spec, Primary, Info);
@@ -6672,19 +6658,13 @@ MarkUsedTemplateParameters(ASTContext &Ctx,
/// Mark the template parameters that are used by the given
/// nested name specifier.
-static void
-MarkUsedTemplateParameters(ASTContext &Ctx,
- NestedNameSpecifier *NNS,
- bool OnlyDeduced,
- unsigned Depth,
- llvm::SmallBitVector &Used) {
- if (!NNS)
+static void MarkUsedTemplateParameters(ASTContext &Ctx, NestedNameSpecifier NNS,
+ bool OnlyDeduced, unsigned Depth,
+ llvm::SmallBitVector &Used) {
+ if (NNS.getKind() != NestedNameSpecifier::Kind::Type)
return;
-
- MarkUsedTemplateParameters(Ctx, NNS->getPrefix(), OnlyDeduced, Depth,
- Used);
- MarkUsedTemplateParameters(Ctx, QualType(NNS->getAsType(), 0),
- OnlyDeduced, Depth, Used);
+ MarkUsedTemplateParameters(Ctx, QualType(NNS.getAsType(), 0), OnlyDeduced,
+ Depth, Used);
}
/// Mark the template parameters that are used by the given
@@ -6758,7 +6738,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
MarkUsedTemplateParameters(Ctx, MemPtr->getPointeeType(), OnlyDeduced,
Depth, Used);
MarkUsedTemplateParameters(Ctx,
- QualType(MemPtr->getQualifier()->getAsType(), 0),
+ QualType(MemPtr->getQualifier().getAsType(), 0),
OnlyDeduced, Depth, Used);
break;
}
@@ -6876,7 +6856,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
}
case Type::InjectedClassName:
- T = cast<InjectedClassNameType>(T)->getInjectedSpecializationType();
+ T = cast<InjectedClassNameType>(T)->getCanonicalInjectedTST();
[[fallthrough]];
case Type::TemplateSpecialization: {
diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
index bdc46a0115a45..4a7b31a942f31 100644
--- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
+++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
@@ -105,22 +105,21 @@ class ExtractTypeForDeductionGuide
return false;
}
- QualType
- RebuildTemplateSpecializationType(TemplateName Template,
- SourceLocation TemplateNameLoc,
- TemplateArgumentListInfo &TemplateArgs) {
+ QualType RebuildTemplateSpecializationType(
+ ElaboratedTypeKeyword Keyword, TemplateName Template,
+ SourceLocation TemplateNameLoc, TemplateArgumentListInfo &TemplateArgs) {
if (!OuterInstantiationArgs ||
!isa_and_present<TypeAliasTemplateDecl>(Template.getAsTemplateDecl()))
- return Base::RebuildTemplateSpecializationType(Template, TemplateNameLoc,
- TemplateArgs);
+ return Base::RebuildTemplateSpecializationType(
+ Keyword, Template, TemplateNameLoc, TemplateArgs);
auto *TATD = cast<TypeAliasTemplateDecl>(Template.getAsTemplateDecl());
auto *Pattern = TATD;
while (Pattern->getInstantiatedFromMemberTemplate())
Pattern = Pattern->getInstantiatedFromMemberTemplate();
if (!mightReferToOuterTemplateParameters(Pattern->getTemplatedDecl()))
- return Base::RebuildTemplateSpecializationType(Template, TemplateNameLoc,
- TemplateArgs);
+ return Base::RebuildTemplateSpecializationType(
+ Keyword, Template, TemplateNameLoc, TemplateArgs);
Decl *NewD =
TypedefNameInstantiator->InstantiateTypeAliasTemplateDecl(TATD);
@@ -131,13 +130,14 @@ class ExtractTypeForDeductionGuide
MaterializedTypedefs.push_back(NewTATD->getTemplatedDecl());
return Base::RebuildTemplateSpecializationType(
- TemplateName(NewTATD), TemplateNameLoc, TemplateArgs);
+ Keyword, TemplateName(NewTATD), TemplateNameLoc, TemplateArgs);
}
QualType TransformTypedefType(TypeLocBuilder &TLB, TypedefTypeLoc TL) {
ASTContext &Context = SemaRef.getASTContext();
- TypedefNameDecl *OrigDecl = TL.getTypedefNameDecl();
+ TypedefNameDecl *OrigDecl = TL.getDecl();
TypedefNameDecl *Decl = OrigDecl;
+ const TypedefType *T = TL.getTypePtr();
// Transform the underlying type of the typedef and clone the Decl only if
// the typedef has a dependent context.
bool InDependentContext = OrigDecl->getDeclContext()->isDependentContext();
@@ -155,7 +155,7 @@ class ExtractTypeForDeductionGuide
// };
// };
if (OuterInstantiationArgs && InDependentContext &&
- TL.getTypePtr()->isInstantiationDependentType()) {
+ T->isInstantiationDependentType()) {
Decl = cast_if_present<TypedefNameDecl>(
TypedefNameInstantiator->InstantiateTypedefNameDecl(
OrigDecl, /*IsTypeAlias=*/isa<TypeAliasDecl>(OrigDecl)));
@@ -180,10 +180,17 @@ class ExtractTypeForDeductionGuide
MaterializedTypedefs.push_back(Decl);
}
- QualType TDTy = Context.getTypedefType(Decl);
- TypedefTypeLoc TypedefTL = TLB.push<TypedefTypeLoc>(TDTy);
- TypedefTL.setNameLoc(TL.getNameLoc());
+ NestedNameSpecifierLoc QualifierLoc = TL.getQualifierLoc();
+ if (QualifierLoc) {
+ QualifierLoc = getDerived().TransformNestedNameSpecifierLoc(QualifierLoc);
+ if (!QualifierLoc)
+ return QualType();
+ }
+ QualType TDTy = Context.getTypedefType(
+ T->getKeyword(), QualifierLoc.getNestedNameSpecifier(), Decl);
+ TLB.push<TypedefTypeLoc>(TDTy).set(TL.getElaboratedKeywordLoc(),
+ QualifierLoc, TL.getNameLoc());
return TDTy;
}
};
@@ -327,7 +334,7 @@ struct ConvertConstructorToDeductionGuideTransform {
DeclarationName DeductionGuideName =
SemaRef.Context.DeclarationNames.getCXXDeductionGuideName(Template);
- QualType DeducedType = SemaRef.Context.getTypeDeclType(Primary);
+ QualType DeducedType = SemaRef.Context.getCanonicalTagType(Primary);
// Index adjustment to apply to convert depth-1 template parameters into
// depth-0 template parameters.
@@ -593,7 +600,10 @@ struct ConvertConstructorToDeductionGuideTransform {
// context of the template), so implicit deduction guides can never collide
// with explicit ones.
QualType ReturnType = DeducedType;
- TLB.pushTypeSpec(ReturnType).setNameLoc(Primary->getLocation());
+ auto TTL = TLB.push<TagTypeLoc>(ReturnType);
+ TTL.setElaboratedKeywordLoc(SourceLocation());
+ TTL.setQualifierLoc(NestedNameSpecifierLoc());
+ TTL.setNameLoc(Primary->getLocation());
// Resolving a wording defect, we also inherit the variadicness of the
// constructor.
@@ -954,7 +964,8 @@ Expr *buildIsDeducibleConstraint(Sema &SemaRef,
SmallVector<TypeSourceInfo *> IsDeducibleTypeTraitArgs = {
Context.getTrivialTypeSourceInfo(
Context.getDeducedTemplateSpecializationType(
- TemplateName(AliasTemplate), /*DeducedType=*/QualType(),
+ ElaboratedTypeKeyword::None, TemplateName(AliasTemplate),
+ /*DeducedType=*/QualType(),
/*IsDependent=*/true),
AliasTemplate->getLocation()), // template specialization type whose
// arguments will be deduced.
@@ -970,10 +981,7 @@ Expr *buildIsDeducibleConstraint(Sema &SemaRef,
std::pair<TemplateDecl *, llvm::ArrayRef<TemplateArgument>>
getRHSTemplateDeclAndArgs(Sema &SemaRef, TypeAliasTemplateDecl *AliasTemplate) {
- // Unwrap the sugared ElaboratedType.
- auto RhsType = AliasTemplate->getTemplatedDecl()
- ->getUnderlyingType()
- .getSingleStepDesugaredType(SemaRef.Context);
+ auto RhsType = AliasTemplate->getTemplatedDecl()->getUnderlyingType();
TemplateDecl *Template = nullptr;
llvm::ArrayRef<TemplateArgument> AliasRhsTemplateArgs;
if (const auto *TST = RhsType->getAs<TemplateSpecializationType>()) {
@@ -1029,12 +1037,10 @@ BuildDeductionGuideForTypeAlias(Sema &SemaRef,
// The (trailing) return type of the deduction guide.
const TemplateSpecializationType *FReturnType =
RType->getAs<TemplateSpecializationType>();
- if (const auto *InjectedCNT = RType->getAs<InjectedClassNameType>())
+ if (const auto *ICNT = RType->getAs<InjectedClassNameType>())
// implicitly-generated deduction guide.
- FReturnType = InjectedCNT->getInjectedTST();
- else if (const auto *ET = RType->getAs<ElaboratedType>())
- // explicit deduction guide.
- FReturnType = ET->getNamedType()->getAs<TemplateSpecializationType>();
+ FReturnType =
+ cast<TemplateSpecializationType>(ICNT->getCanonicalInjectedTST());
assert(FReturnType && "expected to see a return type");
// Deduce template arguments of the deduction guide f from the RHS of
// the alias.
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 9140f00fcd740..7dbaf387f6d13 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -339,45 +339,50 @@ Response HandleFunctionTemplateDecl(Sema &SemaRef,
SemaRef.Context),
/*Final=*/false);
- NestedNameSpecifier *NNS = FTD->getTemplatedDecl()->getQualifier();
-
- while (const Type *Ty = NNS ? NNS->getAsType() : nullptr) {
- if (NNS->isInstantiationDependent()) {
- if (const auto *TSTy = Ty->getAs<TemplateSpecializationType>()) {
- ArrayRef<TemplateArgument> Arguments = TSTy->template_arguments();
- // Prefer template arguments from the injected-class-type if possible.
- // For example,
- // ```cpp
- // template <class... Pack> struct S {
- // template <class T> void foo();
- // };
- // template <class... Pack> template <class T>
- // ^^^^^^^^^^^^^ InjectedTemplateArgs
- // They're of kind TemplateArgument::Pack, not of
- // TemplateArgument::Type.
- // void S<Pack...>::foo() {}
- // ^^^^^^^
- // TSTy->template_arguments() (which are of PackExpansionType)
- // ```
- // This meets the contract in
- // TreeTransform::TryExpandParameterPacks that the template arguments
- // for unexpanded parameters should be of a Pack kind.
- if (TSTy->isCurrentInstantiation()) {
- auto *RD = TSTy->getCanonicalTypeInternal()->getAsCXXRecordDecl();
- if (ClassTemplateDecl *CTD = RD->getDescribedClassTemplate())
- Arguments = CTD->getInjectedTemplateArgs(SemaRef.Context);
- else if (auto *Specialization =
- dyn_cast<ClassTemplateSpecializationDecl>(RD))
- Arguments =
- Specialization->getTemplateInstantiationArgs().asArray();
- }
- Result.addOuterTemplateArguments(
- TSTy->getTemplateName().getAsTemplateDecl(), Arguments,
- /*Final=*/false);
- }
- }
+ NestedNameSpecifier NNS = FTD->getTemplatedDecl()->getQualifier();
+
+ for (const Type *Ty = NNS.getKind() == NestedNameSpecifier::Kind::Type
+ ? NNS.getAsType()
+ : nullptr,
+ *NextTy = nullptr;
+ Ty && Ty->isInstantiationDependentType();
+ Ty = std::exchange(NextTy, nullptr)) {
+ if (NestedNameSpecifier P = Ty->getPrefix();
+ P.getKind() == NestedNameSpecifier::Kind::Type)
+ NextTy = P.getAsType();
+ const auto *TSTy = dyn_cast<TemplateSpecializationType>(Ty);
+ if (!TSTy)
+ continue;
- NNS = NNS->getPrefix();
+ ArrayRef<TemplateArgument> Arguments = TSTy->template_arguments();
+ // Prefer template arguments from the injected-class-type if possible.
+ // For example,
+ // ```cpp
+ // template <class... Pack> struct S {
+ // template <class T> void foo();
+ // };
+ // template <class... Pack> template <class T>
+ // ^^^^^^^^^^^^^ InjectedTemplateArgs
+ // They're of kind TemplateArgument::Pack, not of
+ // TemplateArgument::Type.
+ // void S<Pack...>::foo() {}
+ // ^^^^^^^
+ // TSTy->template_arguments() (which are of PackExpansionType)
+ // ```
+ // This meets the contract in
+ // TreeTransform::TryExpandParameterPacks that the template arguments
+ // for unexpanded parameters should be of a Pack kind.
+ if (TSTy->isCurrentInstantiation()) {
+ auto *RD = TSTy->getCanonicalTypeInternal()->getAsCXXRecordDecl();
+ if (ClassTemplateDecl *CTD = RD->getDescribedClassTemplate())
+ Arguments = CTD->getInjectedTemplateArgs(SemaRef.Context);
+ else if (auto *Specialization =
+ dyn_cast<ClassTemplateSpecializationDecl>(RD))
+ Arguments = Specialization->getTemplateInstantiationArgs().asArray();
+ }
+ Result.addOuterTemplateArguments(
+ TSTy->getTemplateName().getAsTemplateDecl(), Arguments,
+ /*Final=*/false);
}
}
@@ -1165,7 +1170,7 @@ void Sema::PrintInstantiationStack(InstantiationContextDiagFuncRef DiagFunc) {
DiagFunc(Active->PointOfInstantiation,
PDiag(diag::note_member_synthesized_at)
<< MD->isExplicitlyDefaulted() << DFK.asSpecialMember()
- << Context.getTagDeclType(MD->getParent()));
+ << Context.getCanonicalTagType(MD->getParent()));
} else if (DFK.isComparison()) {
QualType RecordType = FD->getParamDecl(0)
->getType()
@@ -1595,15 +1600,9 @@ namespace {
VarDecl *RebuildObjCExceptionDecl(VarDecl *ExceptionDecl,
TypeSourceInfo *TSInfo, QualType T);
- /// Check for tag mismatches when instantiating an
- /// elaborated type.
- QualType RebuildElaboratedType(SourceLocation KeywordLoc,
- ElaboratedTypeKeyword Keyword,
- NestedNameSpecifierLoc QualifierLoc,
- QualType T);
-
TemplateName
- TransformTemplateName(CXXScopeSpec &SS, TemplateName Name,
+ TransformTemplateName(NestedNameSpecifierLoc &QualifierLoc,
+ SourceLocation TemplateKWLoc, TemplateName Name,
SourceLocation NameLoc,
QualType ObjectType = QualType(),
NamedDecl *FirstQualifierInScope = nullptr,
@@ -1649,22 +1648,18 @@ namespace {
return inherited::TransformFunctionProtoType(TLB, TL);
}
- QualType TransformInjectedClassNameType(TypeLocBuilder &TLB,
- InjectedClassNameTypeLoc TL) {
- auto Type = inherited::TransformInjectedClassNameType(TLB, TL);
+ QualType TransformTagType(TypeLocBuilder &TLB, TagTypeLoc TL) {
+ auto Type = inherited::TransformTagType(TLB, TL);
+ if (!Type.isNull())
+ return Type;
// Special case for transforming a deduction guide, we return a
// transformed TemplateSpecializationType.
- if (Type.isNull() &&
- SemaRef.CodeSynthesisContexts.back().Kind ==
- Sema::CodeSynthesisContext::BuildingDeductionGuides) {
- // Return a TemplateSpecializationType for transforming a deduction
- // guide.
- if (auto *ICT = TL.getType()->getAs<InjectedClassNameType>()) {
- auto Type =
- inherited::TransformType(ICT->getInjectedSpecializationType());
- TLB.pushTrivial(SemaRef.Context, Type, TL.getNameLoc());
- return Type;
- }
+ // FIXME: Why is this hack necessary?
+ if (const auto *ICNT = dyn_cast<InjectedClassNameType>(TL.getTypePtr());
+ ICNT && SemaRef.CodeSynthesisContexts.back().Kind ==
+ Sema::CodeSynthesisContext::BuildingDeductionGuides) {
+ Type = inherited::TransformType(ICNT->getCanonicalInjectedTST());
+ TLB.pushTrivial(SemaRef.Context, Type, TL.getNameLoc());
}
return Type;
}
@@ -2050,7 +2045,7 @@ TemplateInstantiator::TransformFirstQualifierInScope(NamedDecl *D,
return cast_or_null<NamedDecl>(TransformDecl(Loc, D));
if (const TagType *Tag = T->getAs<TagType>())
- return Tag->getDecl();
+ return Tag->getOriginalDecl();
// The resulting type is not a tag; complain.
getSema().Diag(Loc, diag::err_nested_name_spec_non_tag) << T;
@@ -2083,41 +2078,10 @@ VarDecl *TemplateInstantiator::RebuildObjCExceptionDecl(VarDecl *ExceptionDecl,
return Var;
}
-QualType
-TemplateInstantiator::RebuildElaboratedType(SourceLocation KeywordLoc,
- ElaboratedTypeKeyword Keyword,
- NestedNameSpecifierLoc QualifierLoc,
- QualType T) {
- if (const TagType *TT = T->getAs<TagType>()) {
- TagDecl* TD = TT->getDecl();
-
- SourceLocation TagLocation = KeywordLoc;
-
- IdentifierInfo *Id = TD->getIdentifier();
-
- // TODO: should we even warn on struct/class mismatches for this? Seems
- // like it's likely to produce a lot of spurious errors.
- if (Id && Keyword != ElaboratedTypeKeyword::None &&
- Keyword != ElaboratedTypeKeyword::Typename) {
- TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForKeyword(Keyword);
- if (!SemaRef.isAcceptableTagRedeclaration(TD, Kind, /*isDefinition*/false,
- TagLocation, Id)) {
- SemaRef.Diag(TagLocation, diag::err_use_with_wrong_tag)
- << Id
- << FixItHint::CreateReplacement(SourceRange(TagLocation),
- TD->getKindName());
- SemaRef.Diag(TD->getLocation(), diag::note_previous_use);
- }
- }
- }
-
- return inherited::RebuildElaboratedType(KeywordLoc, Keyword, QualifierLoc, T);
-}
-
TemplateName TemplateInstantiator::TransformTemplateName(
- CXXScopeSpec &SS, TemplateName Name, SourceLocation NameLoc,
- QualType ObjectType, NamedDecl *FirstQualifierInScope,
- bool AllowInjectedClassName) {
+ NestedNameSpecifierLoc &QualifierLoc, SourceLocation TemplateKWLoc,
+ TemplateName Name, SourceLocation NameLoc, QualType ObjectType,
+ NamedDecl *FirstQualifierInScope, bool AllowInjectedClassName) {
if (TemplateTemplateParmDecl *TTP
= dyn_cast_or_null<TemplateTemplateParmDecl>(Name.getAsTemplateDecl())) {
if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
@@ -2164,6 +2128,12 @@ TemplateName TemplateInstantiator::TransformTemplateName(
TemplateName Template = Arg.getAsTemplate();
assert(!Template.isNull() && "Null template template argument");
+ if (NestedNameSpecifier Qualifier = Template.getQualifier()) {
+ NestedNameSpecifierLocBuilder Builder;
+ Builder.MakeTrivial(SemaRef.Context, Qualifier, NameLoc);
+ QualifierLoc = Builder.getWithLocInContext(SemaRef.Context);
+ }
+
return getSema().Context.getSubstTemplateTemplateParm(
Template, AssociatedDecl, TTP->getIndex(), PackIndex, Final);
}
@@ -2182,9 +2152,9 @@ TemplateName TemplateInstantiator::TransformTemplateName(
getPackIndex(Pack), SubstPack->getFinal());
}
- return inherited::TransformTemplateName(SS, Name, NameLoc, ObjectType,
- FirstQualifierInScope,
- AllowInjectedClassName);
+ return inherited::TransformTemplateName(
+ QualifierLoc, TemplateKWLoc, Name, NameLoc, ObjectType,
+ FirstQualifierInScope, AllowInjectedClassName);
}
ExprResult
@@ -3160,10 +3130,6 @@ namespace {
// Only these types can contain 'auto' types, and subsequently be replaced
// by references to invented parameters.
- TemplateTypeParmDecl *VisitElaboratedType(const ElaboratedType *T) {
- return Visit(T->getNamedType());
- }
-
TemplateTypeParmDecl *VisitPointerType(const PointerType *T) {
return Visit(T->getPointeeType());
}
@@ -4554,14 +4520,14 @@ Sema::SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo,
}
TemplateName
-Sema::SubstTemplateName(NestedNameSpecifierLoc QualifierLoc,
- TemplateName Name, SourceLocation Loc,
+Sema::SubstTemplateName(SourceLocation TemplateKWLoc,
+ NestedNameSpecifierLoc &QualifierLoc, TemplateName Name,
+ SourceLocation NameLoc,
const MultiLevelTemplateArgumentList &TemplateArgs) {
- TemplateInstantiator Instantiator(*this, TemplateArgs, Loc,
+ TemplateInstantiator Instantiator(*this, TemplateArgs, NameLoc,
DeclarationName());
- CXXScopeSpec SS;
- SS.Adopt(QualifierLoc);
- return Instantiator.TransformTemplateName(SS, Name, Loc);
+ return Instantiator.TransformTemplateName(QualifierLoc, TemplateKWLoc, Name,
+ NameLoc);
}
static const Decl *getCanonicalParmVarDecl(const Decl *D) {
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index a25bfd1c48dee..e608b39b49d89 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1483,9 +1483,9 @@ Decl *TemplateDeclInstantiator::InstantiateTypedefNameDecl(TypedefNameDecl *D,
// If the old typedef was the name for linkage purposes of an anonymous
// tag decl, re-establish that relationship for the new typedef.
if (const TagType *oldTagType = D->getUnderlyingType()->getAs<TagType>()) {
- TagDecl *oldTag = oldTagType->getDecl();
+ TagDecl *oldTag = oldTagType->getOriginalDecl();
if (oldTag->getTypedefNameForAnonDecl() == D && !Invalid) {
- TagDecl *newTag = DI->getType()->castAs<TagType>()->getDecl();
+ TagDecl *newTag = DI->getType()->castAs<TagType>()->getOriginalDecl();
assert(!newTag->hasNameForLinkage());
newTag->setTypedefNameForAnonDecl(Typedef);
}
@@ -2241,8 +2241,7 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
CXXRecordDecl *RecordInst = CXXRecordDecl::Create(
SemaRef.Context, Pattern->getTagKind(), DC, Pattern->getBeginLoc(),
- Pattern->getLocation(), Pattern->getIdentifier(), PrevDecl,
- /*DelayTypeCreation=*/true);
+ Pattern->getLocation(), Pattern->getIdentifier(), PrevDecl);
if (QualifierLoc)
RecordInst->setQualifierInfo(QualifierLoc);
@@ -2262,8 +2261,6 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
if (PrevClassTemplate) {
Inst->setCommonPtr(PrevClassTemplate->getCommonPtr());
- RecordInst->setTypeForDecl(
- PrevClassTemplate->getTemplatedDecl()->getTypeForDecl());
const ClassTemplateDecl *MostRecentPrevCT =
PrevClassTemplate->getMostRecentDecl();
TemplateParameterList *PrevParams =
@@ -2297,10 +2294,6 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
Inst->setPreviousDecl(PrevClassTemplate);
- // Trigger creation of the type for the instantiation.
- SemaRef.Context.getInjectedClassNameType(
- RecordInst, Inst->getInjectedClassNameSpecialization());
-
// Finish handling of friends.
if (isFriend) {
DC->makeDeclVisibleInContext(Inst);
@@ -2506,11 +2499,9 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
else
Record = CXXRecordDecl::Create(SemaRef.Context, D->getTagKind(), Owner,
D->getBeginLoc(), D->getLocation(),
- D->getIdentifier(), PrevDecl,
- /*DelayTypeCreation=*/IsInjectedClassName);
- // Link the type of the injected-class-name to that of the outer class.
- if (IsInjectedClassName)
- (void)SemaRef.Context.getTypeDeclType(Record, cast<CXXRecordDecl>(Owner));
+ D->getIdentifier(), PrevDecl);
+
+ Record->setImplicit(D->isImplicit());
// Substitute the nested name specifier, if any.
if (SubstQualifier(D, Record))
@@ -2519,7 +2510,6 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
SemaRef.InstantiateAttrsForDecl(TemplateArgs, D, Record, LateAttrs,
StartingScope);
- Record->setImplicit(D->isImplicit());
// FIXME: Check against AS_none is an ugly hack to work around the issue that
// the tag decls introduced by friend class declarations don't have an access
// specifier. Remove once this area of the code gets sorted out.
@@ -3155,8 +3145,8 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(
Method->setIneligibleOrNotSelected(true);
Method->setRangeEnd(Destructor->getEndLoc());
Method->setDeclName(SemaRef.Context.DeclarationNames.getCXXDestructorName(
- SemaRef.Context.getCanonicalType(
- SemaRef.Context.getTypeDeclType(Record))));
+
+ SemaRef.Context.getCanonicalTagType(Record)));
} else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(D)) {
Method = CXXConversionDecl::Create(
SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo,
@@ -3784,19 +3774,18 @@ TemplateDeclInstantiator::VisitTemplateTemplateParmDecl(
D->getPosition(), D->isParameterPack(), D->getIdentifier(),
D->wasDeclaredWithTypename(), InstParams);
if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) {
- NestedNameSpecifierLoc QualifierLoc =
- D->getDefaultArgument().getTemplateQualifierLoc();
- QualifierLoc =
- SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, TemplateArgs);
+ const TemplateArgumentLoc &A = D->getDefaultArgument();
+ NestedNameSpecifierLoc QualifierLoc = A.getTemplateQualifierLoc();
+ // FIXME: Pass in the template keyword location.
TemplateName TName = SemaRef.SubstTemplateName(
- QualifierLoc, D->getDefaultArgument().getArgument().getAsTemplate(),
- D->getDefaultArgument().getTemplateNameLoc(), TemplateArgs);
+ A.getTemplateKWLoc(), QualifierLoc, A.getArgument().getAsTemplate(),
+ A.getTemplateNameLoc(), TemplateArgs);
if (!TName.isNull())
Param->setDefaultArgument(
SemaRef.Context,
TemplateArgumentLoc(SemaRef.Context, TemplateArgument(TName),
- D->getDefaultArgument().getTemplateQualifierLoc(),
- D->getDefaultArgument().getTemplateNameLoc()));
+ A.getTemplateKWLoc(), QualifierLoc,
+ A.getTemplateNameLoc()));
}
Param->setAccess(AS_public);
Param->setImplicit(D->isImplicit());
@@ -3898,7 +3887,7 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {
if (NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName)
if (auto *RD = dyn_cast<CXXRecordDecl>(SemaRef.CurContext))
NameInfo.setName(SemaRef.Context.DeclarationNames.getCXXConstructorName(
- SemaRef.Context.getCanonicalType(SemaRef.Context.getRecordType(RD))));
+ SemaRef.Context.getCanonicalTagType(RD)));
// We only need to do redeclaration lookups if we're in a class scope (in
// fact, it's not really even possible in non-class scopes).
@@ -4810,18 +4799,13 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
ClassTemplate->findPartialSpecialization(CTAI.CanonicalConverted,
InstParams, InsertPos);
- // Build the type that describes the converted template arguments of the class
- // template partial specialization.
- TypeSourceInfo *WrittenTy = SemaRef.Context.getTemplateSpecializationTypeInfo(
- TemplateName(ClassTemplate), TemplArgInfo->getLAngleLoc(),
- InstTemplateArgs, CTAI.CanonicalConverted);
-
// Create the class template partial specialization declaration.
ClassTemplatePartialSpecializationDecl *InstPartialSpec =
ClassTemplatePartialSpecializationDecl::Create(
SemaRef.Context, PartialSpec->getTagKind(), Owner,
PartialSpec->getBeginLoc(), PartialSpec->getLocation(), InstParams,
- ClassTemplate, CTAI.CanonicalConverted, WrittenTy->getType(),
+ ClassTemplate, CTAI.CanonicalConverted,
+ /*CanonInjectedTST=*/CanQualType(),
/*PrevDecl=*/nullptr);
InstPartialSpec->setTemplateArgsAsWritten(InstTemplateArgs);
@@ -4852,7 +4836,7 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
diag::err_partial_spec_redeclared)
<< InstPartialSpec;
SemaRef.Diag(PrevDecl->getLocation(), diag::note_prev_partial_spec_here)
- << SemaRef.Context.getTypeDeclType(PrevDecl);
+ << SemaRef.Context.getCanonicalTagType(PrevDecl);
return nullptr;
}
@@ -5741,15 +5725,19 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
QualType TransformRecordType(TypeLocBuilder &TLB, RecordTypeLoc TL) {
const RecordType *T = TL.getTypePtr();
RecordDecl *Record = cast_or_null<RecordDecl>(
- getDerived().TransformDecl(TL.getNameLoc(), T->getDecl()));
+ getDerived().TransformDecl(TL.getNameLoc(), T->getOriginalDecl()));
if (Record != OldDecl)
return Base::TransformRecordType(TLB, TL);
- QualType Result = getDerived().RebuildRecordType(NewDecl);
+ // FIXME: transform the rest of the record type.
+ QualType Result = getDerived().RebuildTagType(
+ ElaboratedTypeKeyword::None, /*Qualifier=*/std::nullopt, NewDecl);
if (Result.isNull())
return QualType();
- RecordTypeLoc NewTL = TLB.push<RecordTypeLoc>(Result);
+ TagTypeLoc NewTL = TLB.push<RecordTypeLoc>(Result);
+ NewTL.setElaboratedKeywordLoc(SourceLocation());
+ NewTL.setQualifierLoc(NestedNameSpecifierLoc());
NewTL.setNameLoc(TL.getNameLoc());
return Result;
}
@@ -6910,7 +6898,8 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
Args.addArgument(
getTrivialTemplateArgumentLoc(UnpackedArg, QualType(), Loc));
}
- QualType T = CheckTemplateIdType(TemplateName(TD), Loc, Args);
+ QualType T = CheckTemplateIdType(ElaboratedTypeKeyword::None,
+ TemplateName(TD), Loc, Args);
// We may get a non-null type with errors, in which case
// `getAsCXXRecordDecl` will return `nullptr`. For instance, this
// happens when one of the template arguments is an invalid
@@ -6976,16 +6965,17 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
bool IsBeingInstantiated = false;
if (CXXRecordDecl *Spec = dyn_cast<CXXRecordDecl>(ParentDC)) {
if (!Spec->isDependentContext()) {
- QualType T = Context.getTypeDeclType(Spec);
+ CanQualType T = Context.getCanonicalTagType(Spec);
const RecordType *Tag = T->getAs<RecordType>();
assert(Tag && "type of non-dependent record is not a RecordType");
- if (Tag->isBeingDefined())
+ auto *TagDecl =
+ cast<CXXRecordDecl>(Tag->getOriginalDecl())->getDefinitionOrSelf();
+ if (TagDecl->isBeingDefined())
IsBeingInstantiated = true;
- if (!Tag->isBeingDefined() &&
- RequireCompleteType(Loc, T, diag::err_incomplete_type))
+ else if (RequireCompleteType(Loc, T, diag::err_incomplete_type))
return nullptr;
- ParentDC = Tag->getDecl();
+ ParentDC = TagDecl;
}
}
@@ -7031,8 +7021,8 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
// of member classes, and introduces ordering dependencies via
// template instantiation.
Diag(Loc, diag::err_member_not_yet_instantiated)
- << D->getDeclName()
- << Context.getTypeDeclType(cast<CXXRecordDecl>(ParentDC));
+ << D->getDeclName()
+ << Context.getCanonicalTagType(cast<CXXRecordDecl>(ParentDC));
Diag(D->getLocation(), diag::note_non_instantiated_member_here);
} else if (EnumConstantDecl *ED = dyn_cast<EnumConstantDecl>(D)) {
// This enumeration constant was found when the template was defined,
@@ -7047,7 +7037,7 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
<< D->getDeclName()
<< Context.getTypeDeclType(cast<TypeDecl>(Spec->getDeclContext()));
Diag(Spec->getLocation(), diag::note_enum_specialized_here)
- << Context.getTypeDeclType(Spec);
+ << Context.getCanonicalTagType(Spec);
} else {
// We should have found something, but didn't.
llvm_unreachable("Unable to find instantiation of declaration!");
diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp
index 572dbf2e7393f..b518400b60c7e 100644
--- a/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -155,21 +155,22 @@ class CollectUnexpandedParameterPacksVisitor
/// Suppress traversal into types that do not contain
/// unexpanded parameter packs.
- bool TraverseType(QualType T) override {
+ bool TraverseType(QualType T, bool TraverseQualifier = true) override {
if ((!T.isNull() && T->containsUnexpandedParameterPack()) ||
InLambdaOrBlock)
- return DynamicRecursiveASTVisitor::TraverseType(T);
+ return DynamicRecursiveASTVisitor::TraverseType(T, TraverseQualifier);
return true;
}
/// Suppress traversal into types with location information
/// that do not contain unexpanded parameter packs.
- bool TraverseTypeLoc(TypeLoc TL) override {
+ bool TraverseTypeLoc(TypeLoc TL, bool TraverseQualifier = true) override {
if ((!TL.getType().isNull() &&
TL.getType()->containsUnexpandedParameterPack()) ||
InLambdaOrBlock)
- return DynamicRecursiveASTVisitor::TraverseTypeLoc(TL);
+ return DynamicRecursiveASTVisitor::TraverseTypeLoc(TL,
+ TraverseQualifier);
return true;
}
@@ -195,10 +196,12 @@ class CollectUnexpandedParameterPacksVisitor
/// Suppress traversal of pack expansion expressions and types.
///@{
- bool TraversePackExpansionType(PackExpansionType *T) override {
+ bool TraversePackExpansionType(PackExpansionType *T,
+ bool TraverseQualifier) override {
return true;
}
- bool TraversePackExpansionTypeLoc(PackExpansionTypeLoc TL) override {
+ bool TraversePackExpansionTypeLoc(PackExpansionTypeLoc TL,
+ bool TraverseQualifier) override {
return true;
}
bool TraversePackExpansionExpr(PackExpansionExpr *E) override {
@@ -208,10 +211,12 @@ class CollectUnexpandedParameterPacksVisitor
bool TraversePackIndexingExpr(PackIndexingExpr *E) override {
return DynamicRecursiveASTVisitor::TraverseStmt(E->getIndexExpr());
}
- bool TraversePackIndexingType(PackIndexingType *E) override {
+ bool TraversePackIndexingType(PackIndexingType *E,
+ bool TraverseQualifier) override {
return DynamicRecursiveASTVisitor::TraverseStmt(E->getIndexExpr());
}
- bool TraversePackIndexingTypeLoc(PackIndexingTypeLoc TL) override {
+ bool TraversePackIndexingTypeLoc(PackIndexingTypeLoc TL,
+ bool TraverseQualifier) override {
return DynamicRecursiveASTVisitor::TraverseStmt(TL.getIndexExpr());
}
@@ -515,8 +520,7 @@ bool Sema::DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS,
// C++0x [temp.variadic]p5:
// An appearance of a name of a parameter pack that is not expanded is
// ill-formed.
- if (!SS.getScopeRep() ||
- !SS.getScopeRep()->containsUnexpandedParameterPack())
+ if (!SS.getScopeRep().containsUnexpandedParameterPack())
return false;
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
@@ -644,7 +648,7 @@ Sema::ActOnPackExpansion(const ParsedTemplateArgument &Arg,
return ParsedTemplateArgument();
return ParsedTemplateArgument(Arg.getKind(), Result.get().getAsOpaquePtr(),
- Arg.getLocation());
+ Arg.getNameLoc());
}
case ParsedTemplateArgument::NonType: {
@@ -653,12 +657,12 @@ Sema::ActOnPackExpansion(const ParsedTemplateArgument &Arg,
return ParsedTemplateArgument();
return ParsedTemplateArgument(Arg.getKind(), Result.get(),
- Arg.getLocation());
+ Arg.getNameLoc());
}
case ParsedTemplateArgument::Template:
if (!Arg.getAsTemplate().get().containsUnexpandedParameterPack()) {
- SourceRange R(Arg.getLocation());
+ SourceRange R(Arg.getNameLoc());
if (Arg.getScopeSpec().isValid())
R.setBegin(Arg.getScopeSpec().getBeginLoc());
Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
@@ -1105,8 +1109,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
break;
case DeclaratorChunk::MemberPointer:
- if (Chunk.Mem.Scope().getScopeRep() &&
- Chunk.Mem.Scope().getScopeRep()->containsUnexpandedParameterPack())
+ if (Chunk.Mem.Scope().getScopeRep().containsUnexpandedParameterPack())
return true;
break;
}
@@ -1290,9 +1293,9 @@ TemplateArgumentLoc Sema::getTemplateArgumentPackExpansionPattern(
case TemplateArgument::TemplateExpansion:
Ellipsis = OrigLoc.getTemplateEllipsisLoc();
NumExpansions = Argument.getNumTemplateExpansions();
- return TemplateArgumentLoc(Context, Argument.getPackExpansionPattern(),
- OrigLoc.getTemplateQualifierLoc(),
- OrigLoc.getTemplateNameLoc());
+ return TemplateArgumentLoc(
+ Context, Argument.getPackExpansionPattern(), OrigLoc.getTemplateKWLoc(),
+ OrigLoc.getTemplateQualifierLoc(), OrigLoc.getTemplateNameLoc());
case TemplateArgument::Declaration:
case TemplateArgument::NullPtr:
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 88aa63d3b9e83..b96592f5cb48e 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -1211,14 +1211,11 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
DS.getTypeSpecSign() == TypeSpecifierSign::Unspecified &&
"No qualifiers on tag names!");
+ ElaboratedTypeKeyword Keyword =
+ KeywordHelpers::getKeywordForTypeSpec(DS.getTypeSpecType());
// TypeQuals handled by caller.
- Result = Context.getTypeDeclType(D);
-
- // In both C and C++, make an ElaboratedType.
- ElaboratedTypeKeyword Keyword
- = ElaboratedType::getKeywordForTypeSpec(DS.getTypeSpecType());
- Result = S.getElaboratedType(Keyword, DS.getTypeSpecScope(), Result,
- DS.isTypeSpecOwned() ? D : nullptr);
+ Result = Context.getTagType(Keyword, DS.getTypeSpecScope().getScopeRep(), D,
+ DS.isTypeSpecOwned());
break;
}
case DeclSpec::TST_typename: {
@@ -1241,7 +1238,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
assert(!Result.isNull() && "Didn't get a type for typeof?");
if (!Result->isDependentType())
if (const TagType *TT = Result->getAs<TagType>())
- S.DiagnoseUseOfDecl(TT->getDecl(), DS.getTypeSpecTypeLoc());
+ S.DiagnoseUseOfDecl(TT->getOriginalDecl(), DS.getTypeSpecTypeLoc());
// TypeQuals handled by caller.
Result = Context.getTypeOfType(
Result, DS.getTypeSpecType() == DeclSpec::TST_typeof_unqualType
@@ -2085,7 +2082,7 @@ QualType Sema::BuildArrayType(QualType T, ArraySizeModifier ASM,
// an inheritance model, even if it's inside an unused typedef.
if (Context.getTargetInfo().getCXXABI().isMicrosoft())
if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>())
- if (!MPTy->getQualifier()->isDependent())
+ if (!MPTy->getQualifier().isDependent())
(void)isCompleteType(Loc, T);
} else {
@@ -2120,7 +2117,9 @@ QualType Sema::BuildArrayType(QualType T, ArraySizeModifier ASM,
if (const RecordType *EltTy = T->getAs<RecordType>()) {
// If the element type is a struct or union that contains a variadic
// array, accept it as a GNU extension: C99 6.7.2.1p2.
- if (EltTy->getDecl()->hasFlexibleArrayMember())
+ if (EltTy->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->hasFlexibleArrayMember())
Diag(Loc, diag::ext_flexible_array_in_array) << T;
} else if (T->isObjCObjectType()) {
Diag(Loc, diag::err_objc_array_of_interfaces) << T;
@@ -3462,7 +3461,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
if (DiagID != 0) {
SemaRef.Diag(OwnedTagDecl->getLocation(), DiagID)
- << SemaRef.Context.getTypeDeclType(OwnedTagDecl);
+ << SemaRef.Context.getCanonicalTagType(OwnedTagDecl);
D.setInvalidType(true);
}
}
@@ -3655,11 +3654,22 @@ static void warnAboutRedundantParens(Sema &S, Declarator &D, QualType T) {
// here: even (e.g.) "int ::x" is visually ambiguous even though it's
// formally unambiguous.
if (StartsWithDeclaratorId && D.getCXXScopeSpec().isValid()) {
- for (NestedNameSpecifier *NNS = D.getCXXScopeSpec().getScopeRep(); NNS;
- NNS = NNS->getPrefix()) {
- if (NNS->getKind() == NestedNameSpecifier::Global)
+ NestedNameSpecifier NNS = D.getCXXScopeSpec().getScopeRep();
+ for (;;) {
+ switch (NNS.getKind()) {
+ case NestedNameSpecifier::Kind::Global:
return;
+ case NestedNameSpecifier::Kind::Type:
+ NNS = NNS.getAsType()->getPrefix();
+ continue;
+ case NestedNameSpecifier::Kind::Namespace:
+ NNS = NNS.getAsNamespaceAndPrefix().Prefix;
+ continue;
+ default:
+ goto out;
+ }
}
+ out:;
}
S.Diag(Paren.Loc, diag::warn_redundant_parens_around_declarator)
@@ -3967,7 +3977,8 @@ classifyPointerDeclarator(Sema &S, QualType type, Declarator &declarator,
return PointerDeclaratorKind::NonPointer;
if (auto recordType = type->getAs<RecordType>()) {
- RecordDecl *recordDecl = recordType->getDecl();
+ RecordDecl *recordDecl =
+ recordType->getOriginalDecl()->getDefinitionOrSelf();
// If this is CFErrorRef*, report it as such.
if (numNormalPointers == 2 && numTypeSpecifierPointers < 2 &&
@@ -5101,7 +5112,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// Types shall not be defined in return or parameter types.
TagDecl *Tag = cast<TagDecl>(D.getDeclSpec().getRepAsDecl());
S.Diag(Tag->getLocation(), diag::err_type_defined_in_result_type)
- << Context.getTypeDeclType(Tag);
+ << Context.getCanonicalTagType(Tag);
}
// Exception specs are not allowed in typedefs. Complain, but add it
@@ -5319,7 +5330,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
state.getDeclarator()
.getCXXScopeSpec()
.getScopeRep()
- ->getKind() == NestedNameSpecifier::TypeSpec) ||
+ .getKind() == NestedNameSpecifier::Kind::Type) ||
state.getDeclarator().getContext() ==
DeclaratorContext::Member ||
state.getDeclarator().getContext() ==
@@ -5898,7 +5909,49 @@ namespace {
// int __attr * __attr * __attr *p;
void VisitPointerTypeLoc(PointerTypeLoc TL) { Visit(TL.getNextTypeLoc()); }
void VisitTypedefTypeLoc(TypedefTypeLoc TL) {
- TL.setNameLoc(DS.getTypeSpecTypeLoc());
+ if (DS.getTypeSpecType() == TST_typename) {
+ TypeSourceInfo *TInfo = nullptr;
+ Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
+ if (TInfo) {
+ TL.copy(TInfo->getTypeLoc().castAs<TypedefTypeLoc>());
+ return;
+ }
+ }
+ TL.set(TL.getTypePtr()->getKeyword() != ElaboratedTypeKeyword::None
+ ? DS.getTypeSpecTypeLoc()
+ : SourceLocation(),
+ DS.getTypeSpecScope().getWithLocInContext(Context),
+ DS.getTypeSpecTypeNameLoc());
+ }
+ void VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {
+ if (DS.getTypeSpecType() == TST_typename) {
+ TypeSourceInfo *TInfo = nullptr;
+ Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
+ if (TInfo) {
+ TL.copy(TInfo->getTypeLoc().castAs<UnresolvedUsingTypeLoc>());
+ return;
+ }
+ }
+ TL.set(TL.getTypePtr()->getKeyword() != ElaboratedTypeKeyword::None
+ ? DS.getTypeSpecTypeLoc()
+ : SourceLocation(),
+ DS.getTypeSpecScope().getWithLocInContext(Context),
+ DS.getTypeSpecTypeNameLoc());
+ }
+ void VisitUsingTypeLoc(UsingTypeLoc TL) {
+ if (DS.getTypeSpecType() == TST_typename) {
+ TypeSourceInfo *TInfo = nullptr;
+ Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
+ if (TInfo) {
+ TL.copy(TInfo->getTypeLoc().castAs<UsingTypeLoc>());
+ return;
+ }
+ }
+ TL.set(TL.getTypePtr()->getKeyword() != ElaboratedTypeKeyword::None
+ ? DS.getTypeSpecTypeLoc()
+ : SourceLocation(),
+ DS.getTypeSpecScope().getWithLocInContext(Context),
+ DS.getTypeSpecTypeNameLoc());
}
void VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
TL.setNameLoc(DS.getTypeSpecTypeLoc());
@@ -5929,16 +5982,9 @@ namespace {
}
TypeLoc OldTL = TInfo->getTypeLoc();
- if (TInfo->getType()->getAs<ElaboratedType>()) {
- ElaboratedTypeLoc ElabTL = OldTL.castAs<ElaboratedTypeLoc>();
- TemplateSpecializationTypeLoc NamedTL = ElabTL.getNamedTypeLoc()
- .castAs<TemplateSpecializationTypeLoc>();
- TL.copy(NamedTL);
- } else {
- TL.copy(OldTL.castAs<TemplateSpecializationTypeLoc>());
- assert(TL.getRAngleLoc() == OldTL.castAs<TemplateSpecializationTypeLoc>().getRAngleLoc());
- }
-
+ TL.copy(OldTL.castAs<TemplateSpecializationTypeLoc>());
+ assert(TL.getRAngleLoc() ==
+ OldTL.castAs<TemplateSpecializationTypeLoc>().getRAngleLoc());
}
void VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
assert(DS.getTypeSpecType() == DeclSpec::TST_typeofExpr ||
@@ -5987,24 +6033,6 @@ namespace {
TL.expandBuiltinRange(DS.getTypeSpecWidthRange());
}
}
- void VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
- if (DS.getTypeSpecType() == TST_typename) {
- TypeSourceInfo *TInfo = nullptr;
- Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
- if (TInfo)
- if (auto ETL = TInfo->getTypeLoc().getAs<ElaboratedTypeLoc>()) {
- TL.copy(ETL);
- return;
- }
- }
- const ElaboratedType *T = TL.getTypePtr();
- TL.setElaboratedKeywordLoc(T->getKeyword() != ElaboratedTypeKeyword::None
- ? DS.getTypeSpecTypeLoc()
- : SourceLocation());
- const CXXScopeSpec& SS = DS.getTypeSpecScope();
- TL.setQualifierLoc(SS.getWithLocInContext(Context));
- Visit(TL.getNextTypeLoc().getUnqualifiedLoc());
- }
void VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
assert(DS.getTypeSpecType() == TST_typename);
TypeSourceInfo *TInfo = nullptr;
@@ -6063,7 +6091,29 @@ namespace {
ASTTemplateArgumentListInfo::Create(Context, TemplateArgsInfo));
TL.setConceptReference(CR);
}
+ void VisitDeducedTemplateSpecializationTypeLoc(
+ DeducedTemplateSpecializationTypeLoc TL) {
+ assert(DS.getTypeSpecType() == TST_typename);
+ TypeSourceInfo *TInfo = nullptr;
+ Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
+ assert(TInfo);
+ TL.copy(
+ TInfo->getTypeLoc().castAs<DeducedTemplateSpecializationTypeLoc>());
+ }
void VisitTagTypeLoc(TagTypeLoc TL) {
+ if (DS.getTypeSpecType() == TST_typename) {
+ TypeSourceInfo *TInfo = nullptr;
+ Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
+ if (TInfo) {
+ TL.copy(TInfo->getTypeLoc().castAs<TagTypeLoc>());
+ return;
+ }
+ }
+ TL.setElaboratedKeywordLoc(TL.getTypePtr()->getKeyword() !=
+ ElaboratedTypeKeyword::None
+ ? DS.getTypeSpecTypeLoc()
+ : SourceLocation());
+ TL.setQualifierLoc(DS.getTypeSpecScope().getWithLocInContext(Context));
TL.setNameLoc(DS.getTypeSpecTypeNameLoc());
}
void VisitAtomicTypeLoc(AtomicTypeLoc TL) {
@@ -7029,9 +7079,6 @@ static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,
if (const TypedefType *TT = dyn_cast<TypedefType>(Desugared)) {
Desugared = TT->desugar();
continue;
- } else if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(Desugared)) {
- Desugared = ET->desugar();
- continue;
}
const AttributedType *AT = dyn_cast<AttributedType>(Desugared);
if (!AT)
@@ -9170,11 +9217,9 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
TypeDiagnoser &Diagnoser) {
if (RequireCompleteTypeImpl(Loc, T, Kind, &Diagnoser))
return true;
- if (const TagType *Tag = T->getAs<TagType>()) {
- if (!Tag->getDecl()->isCompleteDefinitionRequired()) {
- Tag->getDecl()->setCompleteDefinitionRequired();
- Consumer.HandleTagDeclRequiredDefinition(Tag->getDecl());
- }
+ if (auto *TD = T->getAsTagDecl(); TD && !TD->isCompleteDefinitionRequired()) {
+ TD->setCompleteDefinitionRequired();
+ Consumer.HandleTagDeclRequiredDefinition(TD);
}
return false;
}
@@ -9312,7 +9357,7 @@ bool Sema::hasReachableDefinition(NamedDecl *D, NamedDecl **Suggested,
/// Locks in the inheritance model for the given class and all of its bases.
static void assignInheritanceModel(Sema &S, CXXRecordDecl *RD) {
- RD = RD->getMostRecentNonInjectedDecl();
+ RD = RD->getMostRecentDecl();
if (!RD->hasAttr<MSInheritanceAttr>()) {
MSInheritanceModel IM;
bool BestCase = false;
@@ -9352,10 +9397,10 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
// assert(!T->isDependentType() &&
// "Can't ask whether a dependent type is complete");
- if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>()) {
+ if (const auto *MPTy = dyn_cast<MemberPointerType>(T.getCanonicalType())) {
if (CXXRecordDecl *RD = MPTy->getMostRecentCXXRecordDecl();
RD && !RD->isDependentType()) {
- QualType T = Context.getTypeDeclType(RD);
+ CanQualType T = Context.getCanonicalTagType(RD);
if (getLangOpts().CompleteMemberPointers && !RD->isBeingDefined() &&
RequireCompleteType(Loc, T, Kind, diag::err_memptr_incomplete))
return true;
@@ -9492,10 +9537,10 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
// If the type was a forward declaration of a class/struct/union
// type, produce a note.
if (Tag && !Tag->isInvalidDecl() && !Tag->getLocation().isInvalid())
- Diag(Tag->getLocation(),
- Tag->isBeingDefined() ? diag::note_type_being_defined
- : diag::note_forward_declaration)
- << Context.getTagDeclType(Tag);
+ Diag(Tag->getLocation(), Tag->isBeingDefined()
+ ? diag::note_type_being_defined
+ : diag::note_forward_declaration)
+ << Context.getCanonicalTagType(Tag);
// If the Objective-C class was a forward declaration, produce a note.
if (IFace && !IFace->isInvalidDecl() && !IFace->getLocation().isInvalid())
@@ -9550,7 +9595,8 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T,
if (!RT)
return true;
- const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ const CXXRecordDecl *RD =
+ cast<CXXRecordDecl>(RT->getOriginalDecl())->getDefinitionOrSelf();
// A partially-defined class type can't be a literal type, because a literal
// class type must have a trivial destructor (which can't be checked until
@@ -9628,15 +9674,6 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, unsigned DiagID) {
return RequireLiteralType(Loc, T, Diagnoser);
}
-QualType Sema::getElaboratedType(ElaboratedTypeKeyword Keyword,
- const CXXScopeSpec &SS, QualType T,
- TagDecl *OwnedTagDecl) {
- if (T.isNull())
- return T;
- return Context.getElaboratedType(
- Keyword, SS.isValid() ? SS.getScopeRep() : nullptr, T, OwnedTagDecl);
-}
-
QualType Sema::BuildTypeofExprType(Expr *E, TypeOfKind Kind) {
assert(!E->hasPlaceholderType() && "unexpected placeholder");
@@ -9647,7 +9684,7 @@ QualType Sema::BuildTypeofExprType(Expr *E, TypeOfKind Kind) {
if (!E->isTypeDependent()) {
QualType T = E->getType();
if (const TagType *TT = T->getAs<TagType>())
- DiagnoseUseOfDecl(TT->getDecl(), E->getExprLoc());
+ DiagnoseUseOfDecl(TT->getOriginalDecl(), E->getExprLoc());
}
return Context.getTypeOfExprType(E, Kind);
}
@@ -9813,8 +9850,7 @@ QualType Sema::BuildPackIndexingType(QualType Pattern, Expr *IndexExpr,
static QualType GetEnumUnderlyingType(Sema &S, QualType BaseType,
SourceLocation Loc) {
assert(BaseType->isEnumeralType());
- EnumDecl *ED = BaseType->castAs<EnumType>()->getDecl();
- assert(ED && "EnumType has no EnumDecl");
+ EnumDecl *ED = BaseType->castAs<EnumType>()->getOriginalDecl();
S.DiagnoseUseOfDecl(ED, Loc);
diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp
index 1d8687e4bf1c1..9b9dd172003a0 100644
--- a/clang/lib/Sema/SemaTypeTraits.cpp
+++ b/clang/lib/Sema/SemaTypeTraits.cpp
@@ -32,8 +32,7 @@ static CXXMethodDecl *LookupSpecialMemberFromXValue(Sema &SemaRef,
RD = RD->getDefinition();
SourceLocation LookupLoc = RD->getLocation();
- CanQualType CanTy = SemaRef.getASTContext().getCanonicalType(
- SemaRef.getASTContext().getTagDeclType(RD));
+ CanQualType CanTy = SemaRef.getASTContext().getCanonicalTagType(RD);
DeclarationName Name;
Expr *Arg = nullptr;
unsigned NumArgs;
@@ -562,7 +561,8 @@ static bool HasNoThrowOperator(const RecordType *RT, OverloadedOperatorKind Op,
bool (CXXRecordDecl::*HasTrivial)() const,
bool (CXXRecordDecl::*HasNonTrivial)() const,
bool (CXXMethodDecl::*IsDesiredOp)() const) {
- CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ CXXRecordDecl *RD =
+ cast<CXXRecordDecl>(RT->getOriginalDecl())->getDefinitionOrSelf();
if ((RD->*HasTrivial)() && !(RD->*HasNonTrivial)())
return true;
@@ -599,6 +599,7 @@ static bool HasNonDeletedDefaultedEqualityComparison(Sema &S,
if (Decl->isLambda())
return Decl->isCapturelessLambda();
+ CanQualType T = S.Context.getCanonicalTagType(Decl);
{
EnterExpressionEvaluationContext UnevaluatedContext(
S, Sema::ExpressionEvaluationContext::Unevaluated);
@@ -606,10 +607,7 @@ static bool HasNonDeletedDefaultedEqualityComparison(Sema &S,
Sema::ContextRAII TUContext(S, S.Context.getTranslationUnitDecl());
// const ClassT& obj;
- OpaqueValueExpr Operand(
- KeyLoc,
- Decl->getTypeForDecl()->getCanonicalTypeUnqualified().withConst(),
- ExprValueKind::VK_LValue);
+ OpaqueValueExpr Operand(KeyLoc, T.withConst(), ExprValueKind::VK_LValue);
UnresolvedSet<16> Functions;
// obj == obj;
S.LookupBinOp(S.TUScope, {}, BinaryOperatorKind::BO_EQ, Functions);
@@ -628,8 +626,7 @@ static bool HasNonDeletedDefaultedEqualityComparison(Sema &S,
return false;
if (!ParamT->isReferenceType() && !Decl->isTriviallyCopyable())
return false;
- if (ParamT.getNonReferenceType()->getUnqualifiedDesugaredType() !=
- Decl->getTypeForDecl())
+ if (!S.Context.hasSameUnqualifiedType(ParamT.getNonReferenceType(), T))
return false;
}
@@ -1613,9 +1610,9 @@ bool Sema::BuiltinIsBaseOf(SourceLocation RhsTLoc, QualType LhsT,
// Unions are never base classes, and never have base classes.
// It doesn't matter if they are complete or not. See PR#41843
- if (lhsRecord && lhsRecord->getDecl()->isUnion())
+ if (lhsRecord && lhsRecord->getOriginalDecl()->isUnion())
return false;
- if (rhsRecord && rhsRecord->getDecl()->isUnion())
+ if (rhsRecord && rhsRecord->getOriginalDecl()->isUnion())
return false;
if (lhsRecord == rhsRecord)
@@ -1629,8 +1626,8 @@ bool Sema::BuiltinIsBaseOf(SourceLocation RhsTLoc, QualType LhsT,
diag::err_incomplete_type_used_in_type_trait_expr))
return false;
- return cast<CXXRecordDecl>(rhsRecord->getDecl())
- ->isDerivedFrom(cast<CXXRecordDecl>(lhsRecord->getDecl()));
+ return cast<CXXRecordDecl>(rhsRecord->getOriginalDecl())
+ ->isDerivedFrom(cast<CXXRecordDecl>(lhsRecord->getOriginalDecl()));
}
static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT,
@@ -1670,8 +1667,9 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT,
diag::err_incomplete_type))
return false;
- return cast<CXXRecordDecl>(DerivedRecord->getDecl())
- ->isVirtuallyDerivedFrom(cast<CXXRecordDecl>(BaseRecord->getDecl()));
+ return cast<CXXRecordDecl>(DerivedRecord->getOriginalDecl())
+ ->isVirtuallyDerivedFrom(
+ cast<CXXRecordDecl>(BaseRecord->getOriginalDecl()));
}
case BTT_IsSame:
return Self.Context.hasSameType(LhsT, RhsT);
@@ -2018,11 +2016,10 @@ static ExtractedTypeTraitInfo ExtractTypeTraitFromExpression(const Expr *E) {
// std::is_xxx<>::value
if (const auto *VD = dyn_cast<VarDecl>(Ref->getDecl());
Ref->hasQualifier() && VD && VD->getIdentifier()->isStr("value")) {
- const Type *T = Ref->getQualifier()->getAsType();
- if (!T)
+ NestedNameSpecifier Qualifier = Ref->getQualifier();
+ if (Qualifier.getKind() != NestedNameSpecifier::Kind::Type)
return std::nullopt;
- const TemplateSpecializationType *Ts =
- T->getAs<TemplateSpecializationType>();
+ const auto *Ts = Qualifier.getAsType()->getAs<TemplateSpecializationType>();
if (!Ts)
return std::nullopt;
const TemplateDecl *D = Ts->getTemplateName().getAsTemplateDecl();
diff --git a/clang/lib/Sema/UsedDeclVisitor.h b/clang/lib/Sema/UsedDeclVisitor.h
index 580d702f96fe5..ad475ab0f42ae 100644
--- a/clang/lib/Sema/UsedDeclVisitor.h
+++ b/clang/lib/Sema/UsedDeclVisitor.h
@@ -71,9 +71,10 @@ class UsedDeclVisitor : public EvaluatedExprVisitor<Derived> {
if (!DestroyedOrNull.isNull()) {
QualType Destroyed = S.Context.getBaseElementType(DestroyedOrNull);
if (const RecordType *DestroyedRec = Destroyed->getAs<RecordType>()) {
- CXXRecordDecl *Record = cast<CXXRecordDecl>(DestroyedRec->getDecl());
- if (Record->getDefinition())
- asImpl().visitUsedDecl(E->getBeginLoc(), S.LookupDestructor(Record));
+ CXXRecordDecl *Record =
+ cast<CXXRecordDecl>(DestroyedRec->getOriginalDecl());
+ if (auto *Def = Record->getDefinition())
+ asImpl().visitUsedDecl(E->getBeginLoc(), S.LookupDestructor(Def));
}
}
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 30e0973149594..353560fab6692 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -5413,7 +5413,7 @@ void ASTReader::InitializeContext() {
Error("Invalid FILE type in AST file");
return;
}
- Context.setFILEDecl(Tag->getDecl());
+ Context.setFILEDecl(Tag->getOriginalDecl());
}
}
}
@@ -5434,7 +5434,7 @@ void ASTReader::InitializeContext() {
Error("Invalid jmp_buf type in AST file");
return;
}
- Context.setjmp_bufDecl(Tag->getDecl());
+ Context.setjmp_bufDecl(Tag->getOriginalDecl());
}
}
}
@@ -5452,7 +5452,7 @@ void ASTReader::InitializeContext() {
else {
const TagType *Tag = Sigjmp_bufType->getAs<TagType>();
assert(Tag && "Invalid sigjmp_buf type in AST file");
- Context.setsigjmp_bufDecl(Tag->getDecl());
+ Context.setsigjmp_bufDecl(Tag->getOriginalDecl());
}
}
}
@@ -5487,7 +5487,7 @@ void ASTReader::InitializeContext() {
else {
const TagType *Tag = Ucontext_tType->getAs<TagType>();
assert(Tag && "Invalid ucontext_t type in AST file");
- Context.setucontext_tDecl(Tag->getDecl());
+ Context.setucontext_tDecl(Tag->getOriginalDecl());
}
}
}
@@ -7107,6 +7107,7 @@ class TypeLocReader : public TypeLocVisitor<TypeLocReader> {
void VisitFunctionTypeLoc(FunctionTypeLoc);
void VisitArrayTypeLoc(ArrayTypeLoc);
+ void VisitTagTypeLoc(TagTypeLoc TL);
};
} // namespace clang
@@ -7253,15 +7254,24 @@ void TypeLocReader::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) {
}
void TypeLocReader::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {
- TL.setNameLoc(readSourceLocation());
+ SourceLocation ElaboratedKeywordLoc = readSourceLocation();
+ NestedNameSpecifierLoc QualifierLoc = ReadNestedNameSpecifierLoc();
+ SourceLocation NameLoc = readSourceLocation();
+ TL.set(ElaboratedKeywordLoc, QualifierLoc, NameLoc);
}
void TypeLocReader::VisitUsingTypeLoc(UsingTypeLoc TL) {
- TL.setNameLoc(readSourceLocation());
+ SourceLocation ElaboratedKeywordLoc = readSourceLocation();
+ NestedNameSpecifierLoc QualifierLoc = ReadNestedNameSpecifierLoc();
+ SourceLocation NameLoc = readSourceLocation();
+ TL.set(ElaboratedKeywordLoc, QualifierLoc, NameLoc);
}
void TypeLocReader::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
- TL.setNameLoc(readSourceLocation());
+ SourceLocation ElaboratedKeywordLoc = readSourceLocation();
+ NestedNameSpecifierLoc QualifierLoc = ReadNestedNameSpecifierLoc();
+ SourceLocation NameLoc = readSourceLocation();
+ TL.set(ElaboratedKeywordLoc, QualifierLoc, NameLoc);
}
void TypeLocReader::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
@@ -7315,17 +7325,27 @@ void TypeLocReader::VisitAutoTypeLoc(AutoTypeLoc TL) {
void TypeLocReader::VisitDeducedTemplateSpecializationTypeLoc(
DeducedTemplateSpecializationTypeLoc TL) {
+ TL.setElaboratedKWLoc(readSourceLocation());
+ TL.setQualifierLoc(ReadNestedNameSpecifierLoc());
TL.setTemplateNameLoc(readSourceLocation());
}
-void TypeLocReader::VisitRecordTypeLoc(RecordTypeLoc TL) {
+void TypeLocReader::VisitTagTypeLoc(TagTypeLoc TL) {
+ TL.setElaboratedKeywordLoc(readSourceLocation());
+ TL.setQualifierLoc(ReadNestedNameSpecifierLoc());
TL.setNameLoc(readSourceLocation());
}
-void TypeLocReader::VisitEnumTypeLoc(EnumTypeLoc TL) {
- TL.setNameLoc(readSourceLocation());
+void TypeLocReader::VisitRecordTypeLoc(RecordTypeLoc TL) {
+ VisitTagTypeLoc(TL);
}
+void TypeLocReader::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) {
+ VisitTagTypeLoc(TL);
+}
+
+void TypeLocReader::VisitEnumTypeLoc(EnumTypeLoc TL) { VisitTagTypeLoc(TL); }
+
void TypeLocReader::VisitAttributedTypeLoc(AttributedTypeLoc TL) {
TL.setAttr(ReadAttr());
}
@@ -7363,14 +7383,18 @@ void TypeLocReader::VisitSubstTemplateTypeParmPackTypeLoc(
void TypeLocReader::VisitTemplateSpecializationTypeLoc(
TemplateSpecializationTypeLoc TL) {
- TL.setTemplateKeywordLoc(readSourceLocation());
- TL.setTemplateNameLoc(readSourceLocation());
- TL.setLAngleLoc(readSourceLocation());
- TL.setRAngleLoc(readSourceLocation());
- for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
- TL.setArgLocInfo(i,
- Reader.readTemplateArgumentLocInfo(
- TL.getTypePtr()->template_arguments()[i].getKind()));
+ SourceLocation ElaboratedKeywordLoc = readSourceLocation();
+ NestedNameSpecifierLoc QualifierLoc = ReadNestedNameSpecifierLoc();
+ SourceLocation TemplateKeywordLoc = readSourceLocation();
+ SourceLocation NameLoc = readSourceLocation();
+ SourceLocation LAngleLoc = readSourceLocation();
+ SourceLocation RAngleLoc = readSourceLocation();
+ TL.set(ElaboratedKeywordLoc, QualifierLoc, TemplateKeywordLoc, NameLoc,
+ LAngleLoc, RAngleLoc);
+ MutableArrayRef<TemplateArgumentLocInfo> Args = TL.getArgLocInfos();
+ for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I)
+ Args[I] = Reader.readTemplateArgumentLocInfo(
+ TL.getTypePtr()->template_arguments()[I].getKind());
}
void TypeLocReader::VisitParenTypeLoc(ParenTypeLoc TL) {
@@ -7378,15 +7402,6 @@ void TypeLocReader::VisitParenTypeLoc(ParenTypeLoc TL) {
TL.setRParenLoc(readSourceLocation());
}
-void TypeLocReader::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
- TL.setElaboratedKeywordLoc(readSourceLocation());
- TL.setQualifierLoc(ReadNestedNameSpecifierLoc());
-}
-
-void TypeLocReader::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) {
- TL.setNameLoc(readSourceLocation());
-}
-
void TypeLocReader::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
TL.setElaboratedKeywordLoc(readSourceLocation());
TL.setQualifierLoc(ReadNestedNameSpecifierLoc());
@@ -7838,18 +7853,15 @@ ASTRecordReader::readTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind) {
return readExpr();
case TemplateArgument::Type:
return readTypeSourceInfo();
- case TemplateArgument::Template: {
- NestedNameSpecifierLoc QualifierLoc =
- readNestedNameSpecifierLoc();
- SourceLocation TemplateNameLoc = readSourceLocation();
- return TemplateArgumentLocInfo(getASTContext(), QualifierLoc,
- TemplateNameLoc, SourceLocation());
- }
+ case TemplateArgument::Template:
case TemplateArgument::TemplateExpansion: {
+ SourceLocation TemplateKWLoc = readSourceLocation();
NestedNameSpecifierLoc QualifierLoc = readNestedNameSpecifierLoc();
SourceLocation TemplateNameLoc = readSourceLocation();
- SourceLocation EllipsisLoc = readSourceLocation();
- return TemplateArgumentLocInfo(getASTContext(), QualifierLoc,
+ SourceLocation EllipsisLoc = Kind == TemplateArgument::TemplateExpansion
+ ? readSourceLocation()
+ : SourceLocation();
+ return TemplateArgumentLocInfo(getASTContext(), TemplateKWLoc, QualifierLoc,
TemplateNameLoc, EllipsisLoc);
}
case TemplateArgument::Null:
@@ -9458,12 +9470,6 @@ void ASTReader::AssignedLambdaNumbering(CXXRecordDecl *Lambda) {
CXXRecordDecl *Previous =
cast<CXXRecordDecl>(Iter->second)->getMostRecentDecl();
Lambda->setPreviousDecl(Previous);
- // FIXME: It will be best to use the Previous type when we creating the
- // lambda directly. But that requires us to get the lambda context decl and
- // lambda index before creating the lambda, which needs a drastic change in
- // the parser.
- const_cast<QualType &>(Lambda->TypeForDecl->CanonicalType) =
- Previous->TypeForDecl->CanonicalType;
return;
}
@@ -9979,48 +9985,37 @@ ASTRecordReader::readNestedNameSpecifierLoc() {
for (unsigned I = 0; I != N; ++I) {
auto Kind = readNestedNameSpecifierKind();
switch (Kind) {
- case NestedNameSpecifier::Identifier: {
- IdentifierInfo *II = readIdentifier();
- SourceRange Range = readSourceRange();
- Builder.Extend(Context, II, Range.getBegin(), Range.getEnd());
- break;
- }
-
- case NestedNameSpecifier::Namespace: {
- NamespaceDecl *NS = readDeclAs<NamespaceDecl>();
+ case NestedNameSpecifier::Kind::Namespace: {
+ auto *NS = readDeclAs<NamespaceBaseDecl>();
SourceRange Range = readSourceRange();
Builder.Extend(Context, NS, Range.getBegin(), Range.getEnd());
break;
}
- case NestedNameSpecifier::NamespaceAlias: {
- NamespaceAliasDecl *Alias = readDeclAs<NamespaceAliasDecl>();
- SourceRange Range = readSourceRange();
- Builder.Extend(Context, Alias, Range.getBegin(), Range.getEnd());
- break;
- }
-
- case NestedNameSpecifier::TypeSpec: {
+ case NestedNameSpecifier::Kind::Type: {
TypeSourceInfo *T = readTypeSourceInfo();
if (!T)
return NestedNameSpecifierLoc();
SourceLocation ColonColonLoc = readSourceLocation();
- Builder.Extend(Context, T->getTypeLoc(), ColonColonLoc);
+ Builder.Make(Context, T->getTypeLoc(), ColonColonLoc);
break;
}
- case NestedNameSpecifier::Global: {
+ case NestedNameSpecifier::Kind::Global: {
SourceLocation ColonColonLoc = readSourceLocation();
Builder.MakeGlobal(Context, ColonColonLoc);
break;
}
- case NestedNameSpecifier::Super: {
+ case NestedNameSpecifier::Kind::Super: {
CXXRecordDecl *RD = readDeclAs<CXXRecordDecl>();
SourceRange Range = readSourceRange();
Builder.MakeSuper(Context, RD, Range.getBegin(), Range.getEnd());
break;
}
+
+ case NestedNameSpecifier::Kind::Null:
+ llvm_unreachable("unexpected null nested name specifier");
}
}
@@ -10416,12 +10411,7 @@ void ASTReader::finishPendingActions() {
// happen now, after the redeclaration chains have been fully wired.
for (Decl *D : PendingDefinitions) {
if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
- if (const TagType *TagT = dyn_cast<TagType>(TD->getTypeForDecl())) {
- // Make sure that the TagType points at the definition.
- const_cast<TagType*>(TagT)->decl = TD;
- }
-
- if (auto RD = dyn_cast<CXXRecordDecl>(D)) {
+ if (auto *RD = dyn_cast<CXXRecordDecl>(TD)) {
for (auto *R = getMostRecentExistingDecl(RD); R;
R = R->getPreviousDecl()) {
assert((R == D) ==
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index 8bde213dc4cb3..ecaf3ad2d9333 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -538,7 +538,11 @@ void ASTDeclReader::Visit(Decl *D) {
if (auto *TD = dyn_cast<TypeDecl>(D)) {
// We have a fully initialized TypeDecl. Read its type now.
- TD->setTypeForDecl(Reader.GetType(DeferredTypeID).getTypePtrOrNull());
+ if (isa<TagDecl, TypedefDecl, TypeAliasDecl>(TD))
+ assert(DeferredTypeID == 0 &&
+ "Deferred type not used for TagDecls and Typedefs");
+ else
+ TD->setTypeForDecl(Reader.GetType(DeferredTypeID).getTypePtrOrNull());
// If this is a tag declaration with a typedef name for linkage, it's safe
// to load that typedef now.
@@ -695,7 +699,8 @@ void ASTDeclReader::VisitTypeDecl(TypeDecl *TD) {
VisitNamedDecl(TD);
TD->setLocStart(readSourceLocation());
// Delay type reading until after we have fully initialized the decl.
- DeferredTypeID = Record.getGlobalTypeID(Record.readInt());
+ if (!isa<TagDecl, TypedefDecl, TypeAliasDecl>(TD))
+ DeferredTypeID = Record.getGlobalTypeID(Record.readInt());
}
RedeclarableResult ASTDeclReader::VisitTypedefNameDecl(TypedefNameDecl *TD) {
@@ -1888,7 +1893,7 @@ void ASTDeclReader::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
D->NamespaceLoc = readSourceLocation();
D->IdentLoc = readSourceLocation();
D->QualifierLoc = Record.readNestedNameSpecifierLoc();
- D->Namespace = readDeclAs<NamedDecl>();
+ D->Namespace = readDeclAs<NamespaceBaseDecl>();
mergeRedeclarable(D, Redecl);
}
@@ -2235,15 +2240,6 @@ RedeclarableResult ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) {
// Merged when we merge the template.
auto *Template = readDeclAs<ClassTemplateDecl>();
D->TemplateOrInstantiation = Template;
- if (!Template->getTemplatedDecl()) {
- // We've not actually loaded the ClassTemplateDecl yet, because we're
- // currently being loaded as its pattern. Rely on it to set up our
- // TypeForDecl (see VisitClassTemplateDecl).
- //
- // Beware: we do not yet know our canonical declaration, and may still
- // get merged once the surrounding class template has got off the ground.
- DeferredTypeID = 0;
- }
break;
}
case CXXRecMemberSpecialization: {
@@ -2477,14 +2473,6 @@ void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
ReadSpecializations(*Loc.F, D, Loc.F->DeclsCursor, /*IsPartial=*/false);
ReadSpecializations(*Loc.F, D, Loc.F->DeclsCursor, /*IsPartial=*/true);
}
-
- if (D->getTemplatedDecl()->TemplateOrInstantiation) {
- // We were loaded before our templated declaration was. We've not set up
- // its corresponding type yet (see VisitCXXRecordDeclImpl), so reconstruct
- // it now.
- Reader.getContext().getInjectedClassNameType(
- D->getTemplatedDecl(), D->getInjectedClassNameSpecialization());
- }
}
void ASTDeclReader::VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D) {
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 1a20fc9595dce..2d41482327c15 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -345,6 +345,7 @@ class TypeLocWriter : public TypeLocVisitor<TypeLocWriter> {
void VisitArrayTypeLoc(ArrayTypeLoc TyLoc);
void VisitFunctionTypeLoc(FunctionTypeLoc TyLoc);
+ void VisitTagTypeLoc(TagTypeLoc TL);
};
} // namespace
@@ -490,14 +491,20 @@ void TypeLocWriter::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) {
}
void TypeLocWriter::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {
+ addSourceLocation(TL.getElaboratedKeywordLoc());
+ Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc());
addSourceLocation(TL.getNameLoc());
}
void TypeLocWriter::VisitUsingTypeLoc(UsingTypeLoc TL) {
+ addSourceLocation(TL.getElaboratedKeywordLoc());
+ Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc());
addSourceLocation(TL.getNameLoc());
}
void TypeLocWriter::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
+ addSourceLocation(TL.getElaboratedKeywordLoc());
+ Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc());
addSourceLocation(TL.getNameLoc());
}
@@ -564,17 +571,27 @@ void TypeLocWriter::VisitAutoTypeLoc(AutoTypeLoc TL) {
void TypeLocWriter::VisitDeducedTemplateSpecializationTypeLoc(
DeducedTemplateSpecializationTypeLoc TL) {
+ addSourceLocation(TL.getElaboratedKWLoc());
+ Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc());
addSourceLocation(TL.getTemplateNameLoc());
}
-void TypeLocWriter::VisitRecordTypeLoc(RecordTypeLoc TL) {
+void TypeLocWriter::VisitTagTypeLoc(TagTypeLoc TL) {
+ addSourceLocation(TL.getElaboratedKeywordLoc());
+ Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc());
addSourceLocation(TL.getNameLoc());
}
-void TypeLocWriter::VisitEnumTypeLoc(EnumTypeLoc TL) {
- addSourceLocation(TL.getNameLoc());
+void TypeLocWriter::VisitRecordTypeLoc(RecordTypeLoc TL) {
+ VisitTagTypeLoc(TL);
+}
+
+void TypeLocWriter::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) {
+ VisitTagTypeLoc(TL);
}
+void TypeLocWriter::VisitEnumTypeLoc(EnumTypeLoc TL) { VisitTagTypeLoc(TL); }
+
void TypeLocWriter::VisitAttributedTypeLoc(AttributedTypeLoc TL) {
Record.AddAttr(TL.getAttr());
}
@@ -612,13 +629,14 @@ void TypeLocWriter::VisitSubstTemplateTypeParmPackTypeLoc(
void TypeLocWriter::VisitTemplateSpecializationTypeLoc(
TemplateSpecializationTypeLoc TL) {
+ addSourceLocation(TL.getElaboratedKeywordLoc());
+ Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc());
addSourceLocation(TL.getTemplateKeywordLoc());
addSourceLocation(TL.getTemplateNameLoc());
addSourceLocation(TL.getLAngleLoc());
addSourceLocation(TL.getRAngleLoc());
for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
- Record.AddTemplateArgumentLocInfo(TL.getArgLoc(i).getArgument().getKind(),
- TL.getArgLoc(i).getLocInfo());
+ Record.AddTemplateArgumentLocInfo(TL.getArgLoc(i));
}
void TypeLocWriter::VisitParenTypeLoc(ParenTypeLoc TL) {
@@ -630,15 +648,6 @@ void TypeLocWriter::VisitMacroQualifiedTypeLoc(MacroQualifiedTypeLoc TL) {
addSourceLocation(TL.getExpansionLoc());
}
-void TypeLocWriter::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
- addSourceLocation(TL.getElaboratedKeywordLoc());
- Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc());
-}
-
-void TypeLocWriter::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) {
- addSourceLocation(TL.getNameLoc());
-}
-
void TypeLocWriter::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
addSourceLocation(TL.getElaboratedKeywordLoc());
Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc());
@@ -654,8 +663,7 @@ void TypeLocWriter::VisitDependentTemplateSpecializationTypeLoc(
addSourceLocation(TL.getLAngleLoc());
addSourceLocation(TL.getRAngleLoc());
for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I)
- Record.AddTemplateArgumentLocInfo(TL.getArgLoc(I).getArgument().getKind(),
- TL.getArgLoc(I).getLocInfo());
+ Record.AddTemplateArgumentLocInfo(TL.getArgLoc(I));
}
void TypeLocWriter::VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL) {
@@ -1033,7 +1041,6 @@ void ASTWriter::WriteBlockInfoBlock() {
RECORD(TYPE_OBJC_INTERFACE);
RECORD(TYPE_OBJC_OBJECT_POINTER);
RECORD(TYPE_DECLTYPE);
- RECORD(TYPE_ELABORATED);
RECORD(TYPE_SUBST_TEMPLATE_TYPE_PARM);
RECORD(TYPE_UNRESOLVED_USING);
RECORD(TYPE_INJECTED_CLASS_NAME);
@@ -6749,22 +6756,22 @@ void ASTRecordWriter::AddCXXTemporary(const CXXTemporary *Temp) {
}
void ASTRecordWriter::AddTemplateArgumentLocInfo(
- TemplateArgument::ArgKind Kind, const TemplateArgumentLocInfo &Arg) {
- switch (Kind) {
+ const TemplateArgumentLoc &Arg) {
+ const TemplateArgumentLocInfo &Info = Arg.getLocInfo();
+ switch (auto K = Arg.getArgument().getKind()) {
case TemplateArgument::Expression:
- AddStmt(Arg.getAsExpr());
+ AddStmt(Info.getAsExpr());
break;
case TemplateArgument::Type:
- AddTypeSourceInfo(Arg.getAsTypeSourceInfo());
+ AddTypeSourceInfo(Info.getAsTypeSourceInfo());
break;
case TemplateArgument::Template:
- AddNestedNameSpecifierLoc(Arg.getTemplateQualifierLoc());
- AddSourceLocation(Arg.getTemplateNameLoc());
- break;
case TemplateArgument::TemplateExpansion:
+ AddSourceLocation(Arg.getTemplateKWLoc());
AddNestedNameSpecifierLoc(Arg.getTemplateQualifierLoc());
AddSourceLocation(Arg.getTemplateNameLoc());
- AddSourceLocation(Arg.getTemplateEllipsisLoc());
+ if (K == TemplateArgument::TemplateExpansion)
+ AddSourceLocation(Arg.getTemplateEllipsisLoc());
break;
case TemplateArgument::Null:
case TemplateArgument::Integral:
@@ -6787,7 +6794,7 @@ void ASTRecordWriter::AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg) {
if (InfoHasSameExpr)
return; // Avoid storing the same expr twice.
}
- AddTemplateArgumentLocInfo(Arg.getArgument().getKind(), Arg.getLocInfo());
+ AddTemplateArgumentLocInfo(Arg);
}
void ASTRecordWriter::AddTypeSourceInfo(TypeSourceInfo *TInfo) {
@@ -7045,54 +7052,50 @@ void ASTRecordWriter::AddQualifierInfo(const QualifierInfo &Info) {
AddTemplateParameterList(Info.TemplParamLists[i]);
}
-void ASTRecordWriter::AddNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
+void ASTRecordWriter::AddNestedNameSpecifierLoc(
+ NestedNameSpecifierLoc QualifierLoc) {
// Nested name specifiers usually aren't too long. I think that 8 would
// typically accommodate the vast majority.
SmallVector<NestedNameSpecifierLoc , 8> NestedNames;
// Push each of the nested-name-specifiers's onto a stack for
// serialization in reverse order.
- while (NNS) {
- NestedNames.push_back(NNS);
- NNS = NNS.getPrefix();
+ while (QualifierLoc) {
+ NestedNames.push_back(QualifierLoc);
+ QualifierLoc = QualifierLoc.getAsNamespaceAndPrefix().Prefix;
}
Record->push_back(NestedNames.size());
while(!NestedNames.empty()) {
- NNS = NestedNames.pop_back_val();
- NestedNameSpecifier::SpecifierKind Kind
- = NNS.getNestedNameSpecifier()->getKind();
- Record->push_back(Kind);
+ QualifierLoc = NestedNames.pop_back_val();
+ NestedNameSpecifier Qualifier = QualifierLoc.getNestedNameSpecifier();
+ NestedNameSpecifier::Kind Kind = Qualifier.getKind();
+ Record->push_back(llvm::to_underlying(Kind));
switch (Kind) {
- case NestedNameSpecifier::Identifier:
- AddIdentifierRef(NNS.getNestedNameSpecifier()->getAsIdentifier());
- AddSourceRange(NNS.getLocalSourceRange());
+ case NestedNameSpecifier::Kind::Namespace:
+ AddDeclRef(Qualifier.getAsNamespaceAndPrefix().Namespace);
+ AddSourceRange(QualifierLoc.getLocalSourceRange());
break;
- case NestedNameSpecifier::Namespace:
- AddDeclRef(NNS.getNestedNameSpecifier()->getAsNamespace());
- AddSourceRange(NNS.getLocalSourceRange());
- break;
-
- case NestedNameSpecifier::NamespaceAlias:
- AddDeclRef(NNS.getNestedNameSpecifier()->getAsNamespaceAlias());
- AddSourceRange(NNS.getLocalSourceRange());
+ case NestedNameSpecifier::Kind::Type: {
+ TypeLoc TL = QualifierLoc.castAsTypeLoc();
+ AddTypeRef(TL.getType());
+ AddTypeLoc(TL);
+ AddSourceLocation(QualifierLoc.getLocalSourceRange().getEnd());
break;
+ }
- case NestedNameSpecifier::TypeSpec:
- AddTypeRef(NNS.getTypeLoc().getType());
- AddTypeLoc(NNS.getTypeLoc());
- AddSourceLocation(NNS.getLocalSourceRange().getEnd());
+ case NestedNameSpecifier::Kind::Global:
+ AddSourceLocation(QualifierLoc.getLocalSourceRange().getEnd());
break;
- case NestedNameSpecifier::Global:
- AddSourceLocation(NNS.getLocalSourceRange().getEnd());
+ case NestedNameSpecifier::Kind::Super:
+ AddDeclRef(Qualifier.getAsSuper());
+ AddSourceRange(QualifierLoc.getLocalSourceRange());
break;
- case NestedNameSpecifier::Super:
- AddDeclRef(NNS.getNestedNameSpecifier()->getAsRecordDecl());
- AddSourceRange(NNS.getLocalSourceRange());
- break;
+ case NestedNameSpecifier::Kind::Null:
+ llvm_unreachable("unexpected null nested name specifier");
}
}
}
diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index b8a68afc30738..b426a9c58a74f 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -524,7 +524,7 @@ void ASTDeclWriter::VisitDecl(Decl *D) {
// bits actually. However, if we changed the order to be 0x0f, then we can
// store it as 0b001111, which takes 6 bits only now.
DeclBits.addBits((uint64_t)D->getModuleOwnershipKind(), /*BitWidth=*/3);
- DeclBits.addBit(D->isReferenced());
+ DeclBits.addBit(D->isThisDeclarationReferenced());
DeclBits.addBit(D->isUsed(false));
DeclBits.addBits(D->getAccess(), /*BitWidth=*/2);
DeclBits.addBit(D->isImplicit());
@@ -601,7 +601,8 @@ void ASTDeclWriter::VisitNamedDecl(NamedDecl *D) {
void ASTDeclWriter::VisitTypeDecl(TypeDecl *D) {
VisitNamedDecl(D);
Record.AddSourceLocation(D->getBeginLoc());
- Record.AddTypeRef(QualType(D->getTypeForDecl(), 0));
+ if (!isa<TagDecl, TypedefDecl, TypeAliasDecl>(D))
+ Record.AddTypeRef(QualType(D->getTypeForDecl(), 0));
}
void ASTDeclWriter::VisitTypedefNameDecl(TypedefNameDecl *D) {
@@ -2559,7 +2560,6 @@ void ASTWriter::WriteDeclAbbrevs() {
Abv->Add(BitCodeAbbrevOp(0)); // AnonDeclNumber
// TypeDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location
- Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type Ref
// TagDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // IdentifierNamespace
Abv->Add(BitCodeAbbrevOp(
@@ -2605,7 +2605,6 @@ void ASTWriter::WriteDeclAbbrevs() {
Abv->Add(BitCodeAbbrevOp(0)); // AnonDeclNumber
// TypeDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location
- Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type Ref
// TagDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // IdentifierNamespace
Abv->Add(BitCodeAbbrevOp(
diff --git a/clang/lib/Serialization/TemplateArgumentHasher.cpp b/clang/lib/Serialization/TemplateArgumentHasher.cpp
index c56138e8893c1..3e8ffea78c2f1 100644
--- a/clang/lib/Serialization/TemplateArgumentHasher.cpp
+++ b/clang/lib/Serialization/TemplateArgumentHasher.cpp
@@ -320,7 +320,7 @@ class TypeVisitorHelper : public TypeVisitor<TypeVisitorHelper> {
void VisitMemberPointerType(const MemberPointerType *T) {
AddQualType(T->getPointeeType());
- AddType(T->getQualifier()->getAsType());
+ AddType(T->getQualifier().getAsType());
if (auto *RD = T->getMostRecentCXXRecordDecl())
AddDecl(RD->getCanonicalDecl());
}
@@ -358,7 +358,7 @@ class TypeVisitorHelper : public TypeVisitor<TypeVisitorHelper> {
AddQualType(T->getReplacementType());
}
- void VisitTagType(const TagType *T) { AddDecl(T->getDecl()); }
+ void VisitTagType(const TagType *T) { AddDecl(T->getOriginalDecl()); }
void VisitRecordType(const RecordType *T) { VisitTagType(T); }
void VisitEnumType(const EnumType *T) { VisitTagType(T); }
@@ -379,10 +379,6 @@ class TypeVisitorHelper : public TypeVisitor<TypeVisitorHelper> {
void VisitTypedefType(const TypedefType *T) { AddDecl(T->getDecl()); }
- void VisitElaboratedType(const ElaboratedType *T) {
- AddQualType(T->getNamedType());
- }
-
void VisitUnaryTransformType(const UnaryTransformType *T) {
AddQualType(T->getUnderlyingType());
AddQualType(T->getBaseType());
diff --git a/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
index 23935647a5826..731e506a5d259 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
@@ -250,7 +250,7 @@ class FindUninitializedField {
bool Find(const TypedValueRegion *R) {
QualType T = R->getValueType();
if (const RecordType *RT = T->getAsStructureType()) {
- const RecordDecl *RD = RT->getDecl()->getDefinition();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinition();
assert(RD && "Referred record has no definition");
for (const auto *I : RD->fields()) {
if (I->isUnnamedBitField())
diff --git a/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
index 0b52c9bd8ac2a..90c6537d71d9d 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
@@ -53,7 +53,7 @@ static bool evenFlexibleArraySize(ASTContext &Ctx, CharUnits RegionSize,
if (!RT)
return false;
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
RecordDecl::field_iterator Iter(RD->field_begin());
RecordDecl::field_iterator End(RD->field_end());
const FieldDecl *Last = nullptr;
diff --git a/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp b/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
index 4982cd59b0a4a..cee744aecb686 100644
--- a/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
@@ -245,7 +245,7 @@ static void recordFixedType(const MemRegion *Region, const CXXMethodDecl *MD,
assert(MD);
ASTContext &Ctx = C.getASTContext();
- QualType Ty = Ctx.getPointerType(Ctx.getRecordType(MD->getParent()));
+ CanQualType Ty = Ctx.getPointerType(Ctx.getCanonicalTagType(MD->getParent()));
ProgramStateRef State = C.getState();
State = setDynamicTypeInfo(State, Region, Ty, /*CanBeSubClassed=*/false);
diff --git a/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp
index 355e82e465e82..054b2e96bd13b 100644
--- a/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp
@@ -148,7 +148,8 @@ void EnumCastOutOfRangeChecker::checkPreStmt(const CastExpr *CE,
// If the isEnumeralType() returned true, then the declaration must exist
// even if it is a stub declaration. It is up to the getDeclValuesForEnum()
// function to handle this.
- const EnumDecl *ED = T->castAs<EnumType>()->getDecl();
+ const EnumDecl *ED =
+ T->castAs<EnumType>()->getOriginalDecl()->getDefinitionOrSelf();
// [[clang::flag_enum]] annotated enums are by definition should be ignored.
if (ED->hasAttr<FlagEnumAttr>())
diff --git a/clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp
index 1cb3848cfed2a..828b6f91d81c2 100644
--- a/clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp
@@ -47,9 +47,6 @@ static bool InNamespace(const Decl *D, StringRef NS) {
}
static bool IsStdString(QualType T) {
- if (const ElaboratedType *QT = T->getAs<ElaboratedType>())
- T = QT->getNamedType();
-
const TypedefType *TT = T->getAs<TypedefType>();
if (!TT)
return false;
@@ -201,7 +198,7 @@ static bool IsPartOfAST(const CXXRecordDecl *R) {
for (const auto &BS : R->bases()) {
QualType T = BS.getType();
if (const RecordType *baseT = T->getAs<RecordType>()) {
- CXXRecordDecl *baseD = cast<CXXRecordDecl>(baseT->getDecl());
+ CXXRecordDecl *baseD = cast<CXXRecordDecl>(baseT->getOriginalDecl());
if (IsPartOfAST(baseD))
return true;
}
@@ -247,7 +244,7 @@ void ASTFieldVisitor::Visit(FieldDecl *D) {
ReportError(T);
if (const RecordType *RT = T->getAs<RecordType>()) {
- const RecordDecl *RD = RT->getDecl()->getDefinition();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinition();
for (auto *I : RD->fields())
Visit(I);
}
diff --git a/clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
index 0aea981252259..b1a7cd7620424 100644
--- a/clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
@@ -148,7 +148,9 @@ void NonNullParamChecker::checkPreCall(const CallEvent &Call,
QualType T = ArgE->getType();
const RecordType *UT = T->getAsUnionType();
- if (!UT || !UT->getDecl()->hasAttr<TransparentUnionAttr>())
+ if (!UT || !UT->getOriginalDecl()
+ ->getMostRecentDecl()
+ ->hasAttr<TransparentUnionAttr>())
continue;
auto CSV = DV->getAs<nonloc::CompoundVal>();
diff --git a/clang/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp
index 7927967093dcb..b5e32495235aa 100644
--- a/clang/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp
@@ -114,10 +114,7 @@ bool NonnullGlobalConstantsChecker::isGlobalConstString(SVal V) const {
if (AT->getAttrKind() == attr::TypeNonNull)
return true;
Ty = AT->getModifiedType();
- } else if (const auto *ET = dyn_cast<ElaboratedType>(T)) {
- const auto *TT = dyn_cast<TypedefType>(ET->getNamedType());
- if (!TT)
- return false;
+ } else if (const auto *TT = dyn_cast<TypedefType>(T)) {
Ty = TT->getDecl()->getUnderlyingType();
// It is sufficient for any intermediate typedef
// to be classified const.
diff --git a/clang/lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp
index f217520d8f4a0..68ab22a44e7b6 100644
--- a/clang/lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp
@@ -197,9 +197,9 @@ void NumberObjectConversionChecker::checkASTCodeBody(const Decl *D,
BugReporter &BR) const {
// Currently this matches CoreFoundation opaque pointer typedefs.
auto CSuspiciousNumberObjectExprM = expr(ignoringParenImpCasts(
- expr(hasType(elaboratedType(namesType(typedefType(
+ expr(hasType(typedefType(
hasDeclaration(anyOf(typedefDecl(hasName("CFNumberRef")),
- typedefDecl(hasName("CFBooleanRef")))))))))
+ typedefDecl(hasName("CFBooleanRef")))))))
.bind("c_object")));
// Currently this matches XNU kernel number-object pointers.
@@ -238,8 +238,7 @@ void NumberObjectConversionChecker::checkASTCodeBody(const Decl *D,
// The .bind here is in order to compose the error message more accurately.
auto ObjCSuspiciousScalarBooleanTypeM =
- qualType(elaboratedType(namesType(
- typedefType(hasDeclaration(typedefDecl(hasName("BOOL")))))))
+ qualType(typedefType(hasDeclaration(typedefDecl(hasName("BOOL")))))
.bind("objc_bool_type");
// The .bind here is in order to compose the error message more accurately.
@@ -252,8 +251,8 @@ void NumberObjectConversionChecker::checkASTCodeBody(const Decl *D,
// for storing pointers.
auto SuspiciousScalarNumberTypeM =
qualType(hasCanonicalType(isInteger()),
- unless(elaboratedType(namesType(typedefType(hasDeclaration(
- typedefDecl(matchesName("^::u?intptr_t$"))))))))
+ unless(typedefType(
+ hasDeclaration(typedefDecl(matchesName("^::u?intptr_t$"))))))
.bind("int_type");
auto SuspiciousScalarTypeM =
diff --git a/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
index d4efbdd54fc22..7ef659518ab1b 100644
--- a/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
@@ -104,7 +104,7 @@ class PaddingChecker : public Checker<check::ASTDecl<TranslationUnitDecl>> {
// There is not enough excess padding to trigger a warning.
return;
}
- reportRecord(RD, BaselinePad, OptimalPad, OptimalFieldsOrder);
+ reportRecord(ASTContext, RD, BaselinePad, OptimalPad, OptimalFieldsOrder);
}
/// Look for arrays of overly padded types. If the padding of the
@@ -123,7 +123,7 @@ class PaddingChecker : public Checker<check::ASTDecl<TranslationUnitDecl>> {
return;
// TODO: Recurse into the fields to see if they have excess padding.
- visitRecord(RT->getDecl(), Elts);
+ visitRecord(RT->getOriginalDecl()->getDefinitionOrSelf(), Elts);
}
bool shouldSkipDecl(const RecordDecl *RD) const {
@@ -159,9 +159,7 @@ class PaddingChecker : public Checker<check::ASTDecl<TranslationUnitDecl>> {
return true;
// Can't layout a template, so skip it. We do still layout the
// instantiations though.
- if (CXXRD->getTypeForDecl()->isDependentType())
- return true;
- if (CXXRD->getTypeForDecl()->isInstantiationDependentType())
+ if (CXXRD->isDependentType())
return true;
}
// How do you reorder fields if you haven't got any?
@@ -306,14 +304,14 @@ class PaddingChecker : public Checker<check::ASTDecl<TranslationUnitDecl>> {
}
void reportRecord(
- const RecordDecl *RD, CharUnits BaselinePad, CharUnits OptimalPad,
+ const ASTContext &Ctx, const RecordDecl *RD, CharUnits BaselinePad,
+ CharUnits OptimalPad,
const SmallVector<const FieldDecl *, 20> &OptimalFieldsOrder) const {
SmallString<100> Buf;
llvm::raw_svector_ostream Os(Buf);
Os << "Excessive padding in '";
- Os << QualType::getAsString(RD->getTypeForDecl(), Qualifiers(),
- LangOptions())
- << "'";
+ QualType(Ctx.getCanonicalTagType(RD)).print(Os, LangOptions());
+ Os << "'";
if (auto *TSD = dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
// TODO: make this show up better in the console output and in
diff --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
index 1c748f9bc1828..c82618fc7a3fb 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
@@ -1589,7 +1589,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
// and we have a TypedefDecl with the name 'FILE'.
for (Decl *D : LookupRes)
if (auto *TD = dyn_cast<TypedefNameDecl>(D))
- return ACtx.getTypeDeclType(TD).getCanonicalType();
+ return ACtx.getCanonicalTypeDeclType(TD);
// Find the first TypeDecl.
// There maybe cases when a function has the same name as a struct.
@@ -1597,7 +1597,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
// int stat(const char *restrict path, struct stat *restrict buf);
for (Decl *D : LookupRes)
if (auto *TD = dyn_cast<TypeDecl>(D))
- return ACtx.getTypeDeclType(TD).getCanonicalType();
+ return ACtx.getCanonicalTypeDeclType(TD);
return std::nullopt;
}
} lookupTy(ACtx);
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index 72199af2f80a5..36c12582a5787 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -181,10 +181,6 @@ template <typename Predicate>
static bool isPtrOfType(const clang::QualType T, Predicate Pred) {
QualType type = T;
while (!type.isNull()) {
- if (auto *elaboratedT = type->getAs<ElaboratedType>()) {
- type = elaboratedT->desugar();
- continue;
- }
if (auto *SpecialT = type->getAs<TemplateSpecializationType>()) {
auto *Decl = SpecialT->getTemplateName().getAsTemplateDecl();
return Decl && Pred(Decl->getNameAsString());
@@ -248,13 +244,15 @@ void RetainTypeChecker::visitTypedef(const TypedefDecl *TD) {
const RecordType *RT = PointeeQT->getAs<RecordType>();
if (!RT) {
if (TD->hasAttr<ObjCBridgeAttr>() || TD->hasAttr<ObjCBridgeMutableAttr>()) {
- if (auto *Type = TD->getTypeForDecl())
- RecordlessTypes.insert(Type);
+ RecordlessTypes.insert(TD->getASTContext()
+ .getTypedefType(ElaboratedTypeKeyword::None,
+ /*Qualifier=*/std::nullopt, TD)
+ .getTypePtr());
}
return;
}
- for (auto *Redecl : RT->getDecl()->getMostRecentDecl()->redecls()) {
+ for (auto *Redecl : RT->getOriginalDecl()->getMostRecentDecl()->redecls()) {
if (Redecl->getAttr<ObjCBridgeAttr>() ||
Redecl->getAttr<ObjCBridgeMutableAttr>()) {
CFPointees.insert(RT);
@@ -266,21 +264,10 @@ void RetainTypeChecker::visitTypedef(const TypedefDecl *TD) {
bool RetainTypeChecker::isUnretained(const QualType QT, bool ignoreARC) {
if (ento::cocoa::isCocoaObjectRef(QT) && (!IsARCEnabled || ignoreARC))
return true;
- auto CanonicalType = QT.getCanonicalType();
- auto PointeeType = CanonicalType->getPointeeType();
- auto *RT = dyn_cast_or_null<RecordType>(PointeeType.getTypePtrOrNull());
- if (!RT) {
- auto *Type = QT.getTypePtrOrNull();
- while (Type) {
- if (RecordlessTypes.contains(Type))
- return true;
- auto *ET = dyn_cast_or_null<ElaboratedType>(Type);
- if (!ET)
- break;
- Type = ET->desugar().getTypePtrOrNull();
- }
- }
- return RT && CFPointees.contains(RT);
+ if (auto *RT = dyn_cast_or_null<RecordType>(
+ QT.getCanonicalType()->getPointeeType().getTypePtrOrNull()))
+ return CFPointees.contains(RT);
+ return RecordlessTypes.contains(QT.getTypePtr());
}
std::optional<bool> isUnretained(const QualType T, bool IsARCEnabled) {
@@ -306,7 +293,7 @@ std::optional<bool> isUnretained(const QualType T, bool IsARCEnabled) {
auto *Record = PointeeType->getAsStructureType();
if (!Record)
return false;
- auto *Decl = Record->getDecl();
+ auto *Decl = Record->getOriginalDecl();
if (!Decl)
return false;
auto TypeName = Decl->getName();
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RefCntblBaseVirtualDtorChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RefCntblBaseVirtualDtorChecker.cpp
index 98c587d62978b..6f3a280971cb8 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RefCntblBaseVirtualDtorChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RefCntblBaseVirtualDtorChecker.cpp
@@ -113,10 +113,6 @@ class DerefFuncDeleteExprVisitor
auto CastType = Cast->getType();
if (auto *PtrType = dyn_cast<PointerType>(CastType)) {
auto PointeeType = PtrType->getPointeeType();
- while (auto *ET = dyn_cast<ElaboratedType>(PointeeType)) {
- if (ET->isSugared())
- PointeeType = ET->desugar();
- }
if (auto *ParmType = dyn_cast<TemplateTypeParmType>(PointeeType)) {
if (ArgList) {
auto ParmIndex = ParmType->getIndex();
@@ -125,13 +121,13 @@ class DerefFuncDeleteExprVisitor
return true;
}
} else if (auto *RD = dyn_cast<RecordType>(PointeeType)) {
- if (RD->getDecl() == ClassDecl)
+ if (declaresSameEntity(RD->getOriginalDecl(), ClassDecl))
return true;
} else if (auto *ST =
dyn_cast<SubstTemplateTypeParmType>(PointeeType)) {
auto Type = ST->getReplacementType();
if (auto *RD = dyn_cast<RecordType>(Type)) {
- if (RD->getDecl() == ClassDecl)
+ if (declaresSameEntity(RD->getOriginalDecl(), ClassDecl))
return true;
}
}
diff --git a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
index 34fcb9b64d555..180056cf68b64 100644
--- a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -89,7 +89,7 @@ static bool isCallback(QualType T) {
T = T->getPointeeType();
if (const RecordType *RT = T->getAsStructureType()) {
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
for (const auto *I : RD->fields()) {
QualType FieldT = I->getType();
if (FieldT->isBlockPointerType() || FieldT->isFunctionPointerType())
@@ -391,7 +391,9 @@ bool CallEvent::isVariadic(const Decl *D) {
static bool isTransparentUnion(QualType T) {
const RecordType *UT = T->getAsUnionType();
- return UT && UT->getDecl()->hasAttr<TransparentUnionAttr>();
+ return UT && UT->getOriginalDecl()
+ ->getMostRecentDecl()
+ ->hasAttr<TransparentUnionAttr>();
}
// In some cases, symbolic cases should be transformed before we associate
@@ -843,7 +845,7 @@ void CXXInstanceCall::getInitialStackFrameContents(
if (MD->getCanonicalDecl() != getDecl()->getCanonicalDecl()) {
ASTContext &Ctx = SVB.getContext();
const CXXRecordDecl *Class = MD->getParent();
- QualType Ty = Ctx.getPointerType(Ctx.getRecordType(Class));
+ CanQualType Ty = Ctx.getPointerType(Ctx.getCanonicalTagType(Class));
// FIXME: CallEvent maybe shouldn't be directly accessing StoreManager.
std::optional<SVal> V =
@@ -854,7 +856,8 @@ void CXXInstanceCall::getInitialStackFrameContents(
// Fall back to a generic pointer cast for this-value.
const CXXMethodDecl *StaticMD = cast<CXXMethodDecl>(getDecl());
const CXXRecordDecl *StaticClass = StaticMD->getParent();
- QualType StaticTy = Ctx.getPointerType(Ctx.getRecordType(StaticClass));
+ CanQualType StaticTy =
+ Ctx.getPointerType(Ctx.getCanonicalTagType(StaticClass));
ThisVal = SVB.evalCast(ThisVal, Ty, StaticTy);
} else
ThisVal = *V;
diff --git a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
index 63ad567ab7151..68bf97e43f3c1 100644
--- a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
+++ b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
@@ -192,11 +192,11 @@ QualType ObjCIvarRegion::getValueType() const {
}
QualType CXXBaseObjectRegion::getValueType() const {
- return QualType(getDecl()->getTypeForDecl(), 0);
+ return getContext().getCanonicalTagType(getDecl());
}
QualType CXXDerivedObjectRegion::getValueType() const {
- return QualType(getDecl()->getTypeForDecl(), 0);
+ return getContext().getCanonicalTagType(getDecl());
}
QualType ParamVarRegion::getValueType() const {
diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
index 388034b087789..02375b0c3469a 100644
--- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -2453,7 +2453,8 @@ NonLoc RegionStoreManager::createLazyBinding(RegionBindingsConstRef B,
SVal RegionStoreManager::getBindingForStruct(RegionBindingsConstRef B,
const TypedValueRegion *R) {
- const RecordDecl *RD = R->getValueType()->castAs<RecordType>()->getDecl();
+ const RecordDecl *RD =
+ R->getValueType()->castAs<RecordType>()->getOriginalDecl();
if (!RD->getDefinition())
return UnknownVal();
@@ -2844,7 +2845,7 @@ RegionStoreManager::bindStruct(LimitedRegionBindingsConstRef B,
assert(T->isStructureOrClassType());
const RecordType* RT = T->castAs<RecordType>();
- const RecordDecl *RD = RT->getDecl();
+ const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
if (!RD->isCompleteDefinition())
return B;
diff --git a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
index 2276c452cce76..a6f4463852a9b 100644
--- a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -320,8 +320,8 @@ loc::MemRegionVal SValBuilder::getCXXThis(const CXXMethodDecl *D,
/// Return a memory region for the 'this' object reference.
loc::MemRegionVal SValBuilder::getCXXThis(const CXXRecordDecl *D,
const StackFrameContext *SFC) {
- const Type *T = D->getTypeForDecl();
- QualType PT = getContext().getPointerType(QualType(T, 0));
+ CanQualType PT =
+ getContext().getPointerType(getContext().getCanonicalTagType(D));
return loc::MemRegionVal(getRegionManager().getCXXThisRegion(PT, SFC));
}
diff --git a/clang/lib/Tooling/ASTDiff/ASTDiff.cpp b/clang/lib/Tooling/ASTDiff/ASTDiff.cpp
index 5f7153cd53ac2..d70a679cc8dd0 100644
--- a/clang/lib/Tooling/ASTDiff/ASTDiff.cpp
+++ b/clang/lib/Tooling/ASTDiff/ASTDiff.cpp
@@ -246,7 +246,7 @@ struct PreorderVisitor : public RecursiveASTVisitor<PreorderVisitor> {
PostTraverse(SavedState);
return true;
}
- bool TraverseType(QualType T) { return true; }
+ bool TraverseType(QualType T, bool TraverseQualifier = true) { return true; }
bool TraverseConstructorInitializer(CXXCtorInitializer *Init) {
if (isNodeExcluded(Tree.AST.getSourceManager(), Init))
return true;
@@ -428,11 +428,12 @@ std::string SyntaxTree::Impl::getDeclValue(const Decl *D) const {
Value += getRelativeName(N) + ";";
if (auto *T = dyn_cast<TypedefNameDecl>(D))
return Value + T->getUnderlyingType().getAsString(TypePP) + ";";
- if (auto *T = dyn_cast<TypeDecl>(D))
- if (T->getTypeForDecl())
- Value +=
- T->getTypeForDecl()->getCanonicalTypeInternal().getAsString(TypePP) +
- ";";
+ if (auto *T = dyn_cast<TypeDecl>(D)) {
+ const ASTContext &Ctx = T->getASTContext();
+ Value +=
+ Ctx.getTypeDeclType(T)->getCanonicalTypeInternal().getAsString(TypePP) +
+ ";";
+ }
if (auto *U = dyn_cast<UsingDirectiveDecl>(D))
return std::string(U->getNominatedNamespace()->getName());
if (auto *A = dyn_cast<AccessSpecDecl>(D)) {
diff --git a/clang/lib/Tooling/Refactoring/Lookup.cpp b/clang/lib/Tooling/Refactoring/Lookup.cpp
index 757fba0404e62..dedde860516ab 100644
--- a/clang/lib/Tooling/Refactoring/Lookup.cpp
+++ b/clang/lib/Tooling/Refactoring/Lookup.cpp
@@ -108,16 +108,6 @@ static StringRef getBestNamespaceSubstr(const DeclContext *DeclA,
}
}
-/// Check if the name specifier begins with a written "::".
-static bool isFullyQualified(const NestedNameSpecifier *NNS) {
- while (NNS) {
- if (NNS->getKind() == NestedNameSpecifier::Global)
- return true;
- NNS = NNS->getPrefix();
- }
- return false;
-}
-
// Adds more scope specifier to the spelled name until the spelling is not
// ambiguous. A spelling is ambiguous if the resolution of the symbol is
// ambiguous. For example, if QName is "::y::bar", the spelling is "y::bar", and
@@ -182,7 +172,7 @@ static std::string disambiguateSpellingInScope(StringRef Spelling,
return Disambiguated;
}
-std::string tooling::replaceNestedName(const NestedNameSpecifier *Use,
+std::string tooling::replaceNestedName(NestedNameSpecifier Use,
SourceLocation UseLoc,
const DeclContext *UseContext,
const NamedDecl *FromDecl,
@@ -217,7 +207,7 @@ std::string tooling::replaceNestedName(const NestedNameSpecifier *Use,
// We work backwards (from most specific possible namespace to least
// specific).
StringRef Suggested = getBestNamespaceSubstr(UseContext, ReplacementString,
- isFullyQualified(Use));
+ Use.isFullyQualified());
return disambiguateSpellingInScope(Suggested, ReplacementString, *UseContext,
UseLoc);
diff --git a/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp b/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp
index 8eff77861f753..d9444110d421c 100644
--- a/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp
+++ b/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp
@@ -107,45 +107,83 @@ class USRLocFindingASTVisitor
};
SourceLocation StartLocationForType(TypeLoc TL) {
+ if (auto QTL = TL.getAs<QualifiedTypeLoc>())
+ TL = QTL.getUnqualifiedLoc();
+
// For elaborated types (e.g. `struct a::A`) we want the portion after the
- // `struct` but including the namespace qualifier, `a::`.
- if (auto ElaboratedTypeLoc = TL.getAs<clang::ElaboratedTypeLoc>()) {
- NestedNameSpecifierLoc NestedNameSpecifier =
- ElaboratedTypeLoc.getQualifierLoc();
- if (NestedNameSpecifier.getNestedNameSpecifier())
- return NestedNameSpecifier.getBeginLoc();
- TL = TL.getNextTypeLoc();
+ // `struct`, including the namespace qualifier, `a::`.
+ switch (TL.getTypeLocClass()) {
+ case TypeLoc::Record:
+ case TypeLoc::InjectedClassName:
+ case TypeLoc::Enum: {
+ auto TTL = TL.castAs<TagTypeLoc>();
+ if (NestedNameSpecifierLoc QualifierLoc = TTL.getQualifierLoc())
+ return QualifierLoc.getBeginLoc();
+ return TTL.getNameLoc();
+ }
+ case TypeLoc::Typedef: {
+ auto TTL = TL.castAs<TypedefTypeLoc>();
+ if (NestedNameSpecifierLoc QualifierLoc = TTL.getQualifierLoc())
+ return QualifierLoc.getBeginLoc();
+ return TTL.getNameLoc();
+ }
+ case TypeLoc::UnresolvedUsing: {
+ auto TTL = TL.castAs<UnresolvedUsingTypeLoc>();
+ if (NestedNameSpecifierLoc QualifierLoc = TTL.getQualifierLoc())
+ return QualifierLoc.getBeginLoc();
+ return TTL.getNameLoc();
+ }
+ case TypeLoc::Using: {
+ auto TTL = TL.castAs<UsingTypeLoc>();
+ if (NestedNameSpecifierLoc QualifierLoc = TTL.getQualifierLoc())
+ return QualifierLoc.getBeginLoc();
+ return TTL.getNameLoc();
+ }
+ case TypeLoc::TemplateSpecialization: {
+ auto TTL = TL.castAs<TemplateSpecializationTypeLoc>();
+ if (NestedNameSpecifierLoc QualifierLoc = TTL.getQualifierLoc())
+ return QualifierLoc.getBeginLoc();
+ return TTL.getTemplateNameLoc();
+ }
+ case TypeLoc::DeducedTemplateSpecialization: {
+ auto DTL = TL.castAs<clang::DeducedTemplateSpecializationTypeLoc>();
+ if (NestedNameSpecifierLoc QualifierLoc = DTL.getQualifierLoc())
+ return QualifierLoc.getBeginLoc();
+ return DTL.getTemplateNameLoc();
+ }
+ case TypeLoc::DependentName: {
+ auto TTL = TL.castAs<DependentNameTypeLoc>();
+ if (NestedNameSpecifierLoc QualifierLoc = TTL.getQualifierLoc())
+ return QualifierLoc.getBeginLoc();
+ return TTL.getNameLoc();
+ }
+ case TypeLoc::DependentTemplateSpecialization: {
+ auto TTL = TL.castAs<DependentTemplateSpecializationTypeLoc>();
+ if (NestedNameSpecifierLoc QualifierLoc = TTL.getQualifierLoc())
+ return QualifierLoc.getBeginLoc();
+ return TTL.getTemplateNameLoc();
+ }
+ default:
+ llvm_unreachable("unhandled TypeLoc class");
}
- return TL.getBeginLoc();
}
SourceLocation EndLocationForType(TypeLoc TL) {
- // Dig past any namespace or keyword qualifications.
- while (TL.getTypeLocClass() == TypeLoc::Elaborated ||
- TL.getTypeLocClass() == TypeLoc::Qualified)
- TL = TL.getNextTypeLoc();
+ if (auto QTL = TL.getAs<QualifiedTypeLoc>())
+ TL = QTL.getUnqualifiedLoc();
// The location for template specializations (e.g. Foo<int>) includes the
// templated types in its location range. We want to restrict this to just
// before the `<` character.
- if (TL.getTypeLocClass() == TypeLoc::TemplateSpecialization) {
- return TL.castAs<TemplateSpecializationTypeLoc>()
- .getLAngleLoc()
- .getLocWithOffset(-1);
- }
+ if (auto TTL = TL.getAs<TemplateSpecializationTypeLoc>())
+ return TTL.getLAngleLoc().getLocWithOffset(-1);
return TL.getEndLoc();
}
-NestedNameSpecifier *GetNestedNameForType(TypeLoc TL) {
- // Dig past any keyword qualifications.
- while (TL.getTypeLocClass() == TypeLoc::Qualified)
- TL = TL.getNextTypeLoc();
-
- // For elaborated types (e.g. `struct a::A`) we want the portion after the
- // `struct` but including the namespace qualifier, `a::`.
- if (auto ElaboratedTypeLoc = TL.getAs<clang::ElaboratedTypeLoc>())
- return ElaboratedTypeLoc.getQualifierLoc().getNestedNameSpecifier();
- return nullptr;
+NestedNameSpecifier GetNestedNameForType(TypeLoc TL) {
+ if (auto QTL = TL.getAs<QualifiedTypeLoc>())
+ TL = QTL.getUnqualifiedLoc();
+ return TL.getPrefix().getNestedNameSpecifier();
}
// Find all locations identified by the given USRs for rename.
@@ -168,14 +206,14 @@ class RenameLocFinder : public RecursiveASTVisitor<RenameLocFinder> {
const NamedDecl *FromDecl;
// The declaration in which the nested name is contained (can be nullptr).
const Decl *Context;
- // The nested name being replaced (can be nullptr).
- const NestedNameSpecifier *Specifier;
+ // The nested name being replaced.
+ NestedNameSpecifier Specifier;
// Determine whether the prefix qualifiers of the NewName should be ignored.
// Normally, we set it to true for the symbol declaration and definition to
// avoid adding prefix qualifiers.
// For example, if it is true and NewName is "a::b::foo", then the symbol
// occurrence which the RenameInfo points to will be renamed to "foo".
- bool IgnorePrefixQualifers;
+ bool IgnorePrefixQualifiers;
};
bool VisitNamedDecl(const NamedDecl *Decl) {
@@ -203,8 +241,8 @@ class RenameLocFinder : public RecursiveASTVisitor<RenameLocFinder> {
EndLoc,
/*FromDecl=*/nullptr,
/*Context=*/nullptr,
- /*Specifier=*/nullptr,
- /*IgnorePrefixQualifers=*/true};
+ /*Specifier=*/std::nullopt,
+ /*IgnorePrefixQualifiers=*/true};
RenameInfos.push_back(Info);
}
}
@@ -217,10 +255,10 @@ class RenameLocFinder : public RecursiveASTVisitor<RenameLocFinder> {
auto EndLoc = Expr->getMemberLoc();
if (isInUSRSet(Decl)) {
RenameInfos.push_back({StartLoc, EndLoc,
- /*FromDecl=*/nullptr,
- /*Context=*/nullptr,
- /*Specifier=*/nullptr,
- /*IgnorePrefixQualifiers=*/true});
+ /*FromDecl=*/nullptr,
+ /*Context=*/nullptr,
+ /*Specifier=*/std::nullopt,
+ /*IgnorePrefixQualifiers=*/true});
}
return true;
}
@@ -235,7 +273,7 @@ class RenameLocFinder : public RecursiveASTVisitor<RenameLocFinder> {
RenameInfos.push_back({StartLoc, EndLoc,
/*FromDecl=*/nullptr,
/*Context=*/nullptr,
- /*Specifier=*/nullptr,
+ /*Specifier=*/std::nullopt,
/*IgnorePrefixQualifiers=*/true});
}
}
@@ -257,7 +295,7 @@ class RenameLocFinder : public RecursiveASTVisitor<RenameLocFinder> {
RenameInfos.push_back({Loc, Loc,
/*FromDecl=*/nullptr,
/*Context=*/nullptr,
- /*Specifier=*/nullptr,
+ /*Specifier=*/std::nullopt,
/*IgnorePrefixQualifiers=*/true});
}
}
@@ -288,7 +326,7 @@ class RenameLocFinder : public RecursiveASTVisitor<RenameLocFinder> {
RenameInfos.push_back({EndLoc, EndLoc,
/*FromDecl=*/nullptr,
/*Context=*/nullptr,
- /*Specifier=*/nullptr,
+ /*Specifier=*/std::nullopt,
/*IgnorePrefixQualifiers=*/true});
return true;
}
@@ -332,7 +370,7 @@ class RenameLocFinder : public RecursiveASTVisitor<RenameLocFinder> {
Decl,
getClosestAncestorDecl(*Expr),
Expr->getQualifier(),
- /*IgnorePrefixQualifers=*/false};
+ /*IgnorePrefixQualifiers=*/false};
RenameInfos.push_back(Info);
}
@@ -350,18 +388,18 @@ class RenameLocFinder : public RecursiveASTVisitor<RenameLocFinder> {
}
bool VisitNestedNameSpecifierLocations(NestedNameSpecifierLoc NestedLoc) {
- if (!NestedLoc.getNestedNameSpecifier()->getAsType())
+ TypeLoc TL = NestedLoc.getAsTypeLoc();
+ if (!TL)
return true;
- if (const auto *TargetDecl =
- getSupportedDeclFromTypeLoc(NestedLoc.getTypeLoc())) {
+ if (const auto *TargetDecl = getSupportedDeclFromTypeLoc(TL)) {
if (isInUSRSet(TargetDecl)) {
RenameInfo Info = {NestedLoc.getBeginLoc(),
- EndLocationForType(NestedLoc.getTypeLoc()),
+ EndLocationForType(TL),
TargetDecl,
getClosestAncestorDecl(NestedLoc),
- NestedLoc.getNestedNameSpecifier()->getPrefix(),
- /*IgnorePrefixQualifers=*/false};
+ /*Specifier=*/std::nullopt,
+ /*IgnorePrefixQualifiers=*/false};
RenameInfos.push_back(Info);
}
}
@@ -411,7 +449,7 @@ class RenameLocFinder : public RecursiveASTVisitor<RenameLocFinder> {
TargetDecl,
getClosestAncestorDecl(Loc),
GetNestedNameForType(Loc),
- /*IgnorePrefixQualifers=*/false};
+ /*IgnorePrefixQualifiers=*/false};
RenameInfos.push_back(Info);
}
return true;
@@ -421,33 +459,17 @@ class RenameLocFinder : public RecursiveASTVisitor<RenameLocFinder> {
// Handle specific template class specialiation cases.
if (const auto *TemplateSpecType =
dyn_cast<TemplateSpecializationType>(Loc.getType())) {
- TypeLoc TargetLoc = Loc;
- if (!ParentTypeLoc.isNull()) {
- if (llvm::isa<ElaboratedType>(ParentTypeLoc.getType()))
- TargetLoc = ParentTypeLoc;
- }
-
if (isInUSRSet(TemplateSpecType->getTemplateName().getAsTemplateDecl())) {
- TypeLoc TargetLoc = Loc;
- // FIXME: Find a better way to handle this case.
- // For the qualified template class specification type like
- // "ns::Foo<int>" in "ns::Foo<int>& f();", we want the parent typeLoc
- // (ElaboratedType) of the TemplateSpecializationType in order to
- // catch the prefix qualifiers "ns::".
- if (!ParentTypeLoc.isNull() &&
- llvm::isa<ElaboratedType>(ParentTypeLoc.getType()))
- TargetLoc = ParentTypeLoc;
-
- auto StartLoc = StartLocationForType(TargetLoc);
- auto EndLoc = EndLocationForType(TargetLoc);
+ auto StartLoc = StartLocationForType(Loc);
+ auto EndLoc = EndLocationForType(Loc);
if (IsValidEditLoc(Context.getSourceManager(), StartLoc)) {
RenameInfo Info = {
StartLoc,
EndLoc,
TemplateSpecType->getTemplateName().getAsTemplateDecl(),
- getClosestAncestorDecl(DynTypedNode::create(TargetLoc)),
- GetNestedNameForType(TargetLoc),
- /*IgnorePrefixQualifers=*/false};
+ getClosestAncestorDecl(DynTypedNode::create(Loc)),
+ GetNestedNameForType(Loc),
+ /*IgnorePrefixQualifiers=*/false};
RenameInfos.push_back(Info);
}
}
@@ -469,12 +491,7 @@ class RenameLocFinder : public RecursiveASTVisitor<RenameLocFinder> {
const NamedDecl *getSupportedDeclFromTypeLoc(TypeLoc Loc) {
if (const auto* TT = Loc.getType()->getAs<clang::TypedefType>())
return TT->getDecl();
- if (const auto *RD = Loc.getType()->getAsCXXRecordDecl())
- return RD;
- if (const auto *ED =
- llvm::dyn_cast_or_null<EnumDecl>(Loc.getType()->getAsTagDecl()))
- return ED;
- return nullptr;
+ return Loc.getType()->getAsTagDecl();
}
// Get the closest ancester which is a declaration of a given AST node.
@@ -549,7 +566,7 @@ createRenameAtomicChanges(llvm::ArrayRef<std::string> USRs,
for (const auto &RenameInfo : Finder.getRenameInfos()) {
std::string ReplacedName = NewName.str();
- if (RenameInfo.IgnorePrefixQualifers) {
+ if (RenameInfo.IgnorePrefixQualifiers) {
// Get the name without prefix qualifiers from NewName.
size_t LastColonPos = NewName.find_last_of(':');
if (LastColonPos != std::string::npos)
diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp
index caac719caf8e8..546161cee33f4 100644
--- a/clang/lib/Tooling/Syntax/BuildTree.cpp
+++ b/clang/lib/Tooling/Syntax/BuildTree.cpp
@@ -918,98 +918,91 @@ class BuildTreeVisitor : public RecursiveASTVisitor<BuildTreeVisitor> {
return true;
}
- // FIXME: Fix `NestedNameSpecifierLoc::getLocalSourceRange` for the
- // `DependentTemplateSpecializationType` case.
- /// Given a nested-name-specifier return the range for the last name
- /// specifier.
- ///
- /// e.g. `std::T::template X<U>::` => `template X<U>::`
- SourceRange getLocalSourceRange(const NestedNameSpecifierLoc &NNSLoc) {
- auto SR = NNSLoc.getLocalSourceRange();
-
- // The method `NestedNameSpecifierLoc::getLocalSourceRange` *should*
- // return the desired `SourceRange`, but there is a corner case. For a
- // `DependentTemplateSpecializationType` this method returns its
- // qualifiers as well, in other words in the example above this method
- // returns `T::template X<U>::` instead of only `template X<U>::`
- if (auto TL = NNSLoc.getTypeLoc()) {
- if (auto DependentTL =
- TL.getAs<DependentTemplateSpecializationTypeLoc>()) {
- // The 'template' keyword is always present in dependent template
- // specializations. Except in the case of incorrect code
- // TODO: Treat the case of incorrect code.
- SR.setBegin(DependentTL.getTemplateKeywordLoc());
- }
- }
-
- return SR;
- }
-
- syntax::NodeKind getNameSpecifierKind(const NestedNameSpecifier &NNS) {
- switch (NNS.getKind()) {
- case NestedNameSpecifier::Global:
- return syntax::NodeKind::GlobalNameSpecifier;
- case NestedNameSpecifier::Namespace:
- case NestedNameSpecifier::NamespaceAlias:
- case NestedNameSpecifier::Identifier:
- return syntax::NodeKind::IdentifierNameSpecifier;
- case NestedNameSpecifier::TypeSpec: {
- const auto *NNSType = NNS.getAsType();
- assert(NNSType);
- if (isa<DecltypeType>(NNSType))
- return syntax::NodeKind::DecltypeNameSpecifier;
- if (isa<TemplateSpecializationType, DependentTemplateSpecializationType>(
- NNSType))
- return syntax::NodeKind::SimpleTemplateNameSpecifier;
- return syntax::NodeKind::IdentifierNameSpecifier;
- }
- default:
- // FIXME: Support Microsoft's __super
- llvm::report_fatal_error("We don't yet support the __super specifier",
- true);
- }
+ syntax::NameSpecifier *buildIdentifier(SourceRange SR,
+ bool DropBack = false) {
+ auto NameSpecifierTokens = Builder.getRange(SR).drop_back(DropBack);
+ assert(NameSpecifierTokens.size() == 1);
+ Builder.markChildToken(NameSpecifierTokens.begin(),
+ syntax::NodeRole::Unknown);
+ auto *NS = new (allocator()) syntax::IdentifierNameSpecifier;
+ Builder.foldNode(NameSpecifierTokens, NS, nullptr);
+ return NS;
+ }
+
+ syntax::NameSpecifier *buildSimpleTemplateName(SourceRange SR) {
+ auto NameSpecifierTokens = Builder.getRange(SR);
+ // TODO: Build `SimpleTemplateNameSpecifier` children and implement
+ // accessors to them.
+ // Be aware, we cannot do that simply by calling `TraverseTypeLoc`,
+ // some `TypeLoc`s have inside them the previous name specifier and
+ // we want to treat them independently.
+ auto *NS = new (allocator()) syntax::SimpleTemplateNameSpecifier;
+ Builder.foldNode(NameSpecifierTokens, NS, nullptr);
+ return NS;
}
syntax::NameSpecifier *
buildNameSpecifier(const NestedNameSpecifierLoc &NNSLoc) {
assert(NNSLoc.hasQualifier());
- auto NameSpecifierTokens =
- Builder.getRange(getLocalSourceRange(NNSLoc)).drop_back();
- switch (getNameSpecifierKind(*NNSLoc.getNestedNameSpecifier())) {
- case syntax::NodeKind::GlobalNameSpecifier:
+ switch (NNSLoc.getNestedNameSpecifier().getKind()) {
+ case NestedNameSpecifier::Kind::Global:
return new (allocator()) syntax::GlobalNameSpecifier;
- case syntax::NodeKind::IdentifierNameSpecifier: {
- assert(NameSpecifierTokens.size() == 1);
- Builder.markChildToken(NameSpecifierTokens.begin(),
- syntax::NodeRole::Unknown);
- auto *NS = new (allocator()) syntax::IdentifierNameSpecifier;
- Builder.foldNode(NameSpecifierTokens, NS, nullptr);
- return NS;
- }
- case syntax::NodeKind::SimpleTemplateNameSpecifier: {
- // TODO: Build `SimpleTemplateNameSpecifier` children and implement
- // accessors to them.
- // Be aware, we cannot do that simply by calling `TraverseTypeLoc`,
- // some `TypeLoc`s have inside them the previous name specifier and
- // we want to treat them independently.
- auto *NS = new (allocator()) syntax::SimpleTemplateNameSpecifier;
- Builder.foldNode(NameSpecifierTokens, NS, nullptr);
- return NS;
- }
- case syntax::NodeKind::DecltypeNameSpecifier: {
- const auto TL = NNSLoc.getTypeLoc().castAs<DecltypeTypeLoc>();
- if (!RecursiveASTVisitor::TraverseDecltypeTypeLoc(TL))
- return nullptr;
- auto *NS = new (allocator()) syntax::DecltypeNameSpecifier;
- // TODO: Implement accessor to `DecltypeNameSpecifier` inner
- // `DecltypeTypeLoc`.
- // For that add mapping from `TypeLoc` to `syntax::Node*` then:
- // Builder.markChild(TypeLoc, syntax::NodeRole);
- Builder.foldNode(NameSpecifierTokens, NS, nullptr);
- return NS;
+
+ case NestedNameSpecifier::Kind::Namespace:
+ return buildIdentifier(NNSLoc.getLocalSourceRange(), /*DropBack=*/true);
+
+ case NestedNameSpecifier::Kind::Type: {
+ TypeLoc TL = NNSLoc.castAsTypeLoc();
+ switch (TL.getTypeLocClass()) {
+ case TypeLoc::Record:
+ case TypeLoc::InjectedClassName:
+ case TypeLoc::Enum:
+ return buildIdentifier(TL.castAs<TagTypeLoc>().getNameLoc());
+ case TypeLoc::Typedef:
+ return buildIdentifier(TL.castAs<TypedefTypeLoc>().getNameLoc());
+ case TypeLoc::UnresolvedUsing:
+ return buildIdentifier(
+ TL.castAs<UnresolvedUsingTypeLoc>().getNameLoc());
+ case TypeLoc::Using:
+ return buildIdentifier(TL.castAs<UsingTypeLoc>().getNameLoc());
+ case TypeLoc::DependentName:
+ return buildIdentifier(TL.castAs<DependentNameTypeLoc>().getNameLoc());
+ case TypeLoc::TemplateSpecialization: {
+ auto TST = TL.castAs<TemplateSpecializationTypeLoc>();
+ SourceLocation BeginLoc = TST.getTemplateKeywordLoc();
+ if (BeginLoc.isInvalid())
+ BeginLoc = TST.getTemplateNameLoc();
+ return buildSimpleTemplateName({BeginLoc, TST.getEndLoc()});
+ }
+ case TypeLoc::DependentTemplateSpecialization: {
+ auto DT = TL.castAs<DependentTemplateSpecializationTypeLoc>();
+ SourceLocation BeginLoc = DT.getTemplateKeywordLoc();
+ if (BeginLoc.isInvalid())
+ BeginLoc = DT.getTemplateNameLoc();
+ return buildSimpleTemplateName({BeginLoc, DT.getEndLoc()});
+ }
+ case TypeLoc::Decltype: {
+ const auto DTL = TL.castAs<DecltypeTypeLoc>();
+ if (!RecursiveASTVisitor::TraverseDecltypeTypeLoc(
+ DTL, /*TraverseQualifier=*/true))
+ return nullptr;
+ auto *NS = new (allocator()) syntax::DecltypeNameSpecifier;
+ // TODO: Implement accessor to `DecltypeNameSpecifier` inner
+ // `DecltypeTypeLoc`.
+ // For that add mapping from `TypeLoc` to `syntax::Node*` then:
+ // Builder.markChild(TypeLoc, syntax::NodeRole);
+ Builder.foldNode(Builder.getRange(DTL.getLocalSourceRange()), NS,
+ nullptr);
+ return NS;
+ }
+ default:
+ return buildIdentifier(TL.getLocalSourceRange());
+ }
}
default:
- llvm_unreachable("getChildKind() does not return this value");
+ // FIXME: Support Microsoft's __super
+ llvm::report_fatal_error("We don't yet support the __super specifier",
+ true);
}
}
@@ -1020,12 +1013,16 @@ class BuildTreeVisitor : public RecursiveASTVisitor<BuildTreeVisitor> {
bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc QualifierLoc) {
if (!QualifierLoc)
return true;
- for (auto It = QualifierLoc; It; It = It.getPrefix()) {
+ for (auto It = QualifierLoc; It; /**/) {
auto *NS = buildNameSpecifier(It);
if (!NS)
return false;
Builder.markChild(NS, syntax::NodeRole::ListElement);
Builder.markChildToken(It.getEndLoc(), syntax::NodeRole::ListDelimiter);
+ if (TypeLoc TL = It.getAsTypeLoc())
+ It = TL.getPrefix();
+ else
+ It = It.getAsNamespaceAndPrefix().Prefix;
}
Builder.foldNode(Builder.getRange(QualifierLoc.getSourceRange()),
new (allocator()) syntax::NestedNameSpecifier,
@@ -1329,7 +1326,7 @@ class BuildTreeVisitor : public RecursiveASTVisitor<BuildTreeVisitor> {
// FIXME: Deleting the `TraverseParenTypeLoc` override doesn't change test
// results. Find test coverage or remove it.
- bool TraverseParenTypeLoc(ParenTypeLoc L) {
+ bool TraverseParenTypeLoc(ParenTypeLoc L, bool TraverseQualifier) {
// We reverse order of traversal to get the proper syntax structure.
if (!WalkUpFromParenTypeLoc(L))
return false;
@@ -1392,7 +1389,8 @@ class BuildTreeVisitor : public RecursiveASTVisitor<BuildTreeVisitor> {
return WalkUpFromFunctionTypeLoc(L);
}
- bool TraverseMemberPointerTypeLoc(MemberPointerTypeLoc L) {
+ bool TraverseMemberPointerTypeLoc(MemberPointerTypeLoc L,
+ bool TraverseQualifier) {
// In the source code "void (Y::*mp)()" `MemberPointerTypeLoc` corresponds
// to "Y::*" but it points to a `ParenTypeLoc` that corresponds to
// "(Y::*mp)" We thus reverse the order of traversal to get the proper
diff --git a/clang/lib/Tooling/Transformer/RangeSelector.cpp b/clang/lib/Tooling/Transformer/RangeSelector.cpp
index 00f4611ddb5d4..171c786bc366f 100644
--- a/clang/lib/Tooling/Transformer/RangeSelector.cpp
+++ b/clang/lib/Tooling/Transformer/RangeSelector.cpp
@@ -222,14 +222,10 @@ RangeSelector transformer::name(std::string ID) {
return CharSourceRange::getTokenRange(L, L);
}
if (const auto *T = Node.get<TypeLoc>()) {
- TypeLoc Loc = *T;
- auto ET = Loc.getAs<ElaboratedTypeLoc>();
- if (!ET.isNull())
- Loc = ET.getNamedTypeLoc();
- if (auto SpecLoc = Loc.getAs<TemplateSpecializationTypeLoc>();
+ if (auto SpecLoc = T->getAs<TemplateSpecializationTypeLoc>();
!SpecLoc.isNull())
return CharSourceRange::getTokenRange(SpecLoc.getTemplateNameLoc());
- return CharSourceRange::getTokenRange(Loc.getSourceRange());
+ return CharSourceRange::getTokenRange(T->getSourceRange());
}
return typeError(ID, Node.getNodeKind(),
"DeclRefExpr, NamedDecl, CXXCtorInitializer, TypeLoc");
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 9089984fa4a54..08e34d7261626 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -1420,90 +1420,25 @@ bool CursorVisitor::VisitDeclarationNameInfo(DeclarationNameInfo Name) {
llvm_unreachable("Invalid DeclarationName::Kind!");
}
-bool CursorVisitor::VisitNestedNameSpecifier(NestedNameSpecifier *NNS,
- SourceRange Range) {
- // FIXME: This whole routine is a hack to work around the lack of proper
- // source information in nested-name-specifiers (PR5791). Since we do have
- // a beginning source location, we can visit the first component of the
- // nested-name-specifier, if it's a single-token component.
- if (!NNS)
- return false;
-
- // Get the first component in the nested-name-specifier.
- while (NestedNameSpecifier *Prefix = NNS->getPrefix())
- NNS = Prefix;
-
- switch (NNS->getKind()) {
- case NestedNameSpecifier::Namespace:
- return Visit(
- MakeCursorNamespaceRef(NNS->getAsNamespace(), Range.getBegin(), TU));
-
- case NestedNameSpecifier::NamespaceAlias:
- return Visit(MakeCursorNamespaceRef(NNS->getAsNamespaceAlias(),
- Range.getBegin(), TU));
-
- case NestedNameSpecifier::TypeSpec: {
- // If the type has a form where we know that the beginning of the source
- // range matches up with a reference cursor. Visit the appropriate reference
- // cursor.
- const Type *T = NNS->getAsType();
- if (const TypedefType *Typedef = dyn_cast<TypedefType>(T))
- return Visit(MakeCursorTypeRef(Typedef->getDecl(), Range.getBegin(), TU));
- if (const TagType *Tag = dyn_cast<TagType>(T))
- return Visit(MakeCursorTypeRef(Tag->getDecl(), Range.getBegin(), TU));
- if (const TemplateSpecializationType *TST =
- dyn_cast<TemplateSpecializationType>(T))
- return VisitTemplateName(TST->getTemplateName(), Range.getBegin());
- break;
- }
-
- case NestedNameSpecifier::Global:
- case NestedNameSpecifier::Identifier:
- case NestedNameSpecifier::Super:
- break;
- }
-
- return false;
-}
-
bool CursorVisitor::VisitNestedNameSpecifierLoc(
NestedNameSpecifierLoc Qualifier) {
- SmallVector<NestedNameSpecifierLoc, 4> Qualifiers;
- for (; Qualifier; Qualifier = Qualifier.getPrefix())
- Qualifiers.push_back(Qualifier);
-
- while (!Qualifiers.empty()) {
- NestedNameSpecifierLoc Q = Qualifiers.pop_back_val();
- NestedNameSpecifier *NNS = Q.getNestedNameSpecifier();
- switch (NNS->getKind()) {
- case NestedNameSpecifier::Namespace:
- if (Visit(MakeCursorNamespaceRef(NNS->getAsNamespace(),
- Q.getLocalBeginLoc(), TU)))
- return true;
-
- break;
-
- case NestedNameSpecifier::NamespaceAlias:
- if (Visit(MakeCursorNamespaceRef(NNS->getAsNamespaceAlias(),
- Q.getLocalBeginLoc(), TU)))
- return true;
-
- break;
-
- case NestedNameSpecifier::TypeSpec:
- if (Visit(Q.getTypeLoc()))
- return true;
-
- break;
-
- case NestedNameSpecifier::Global:
- case NestedNameSpecifier::Identifier:
- case NestedNameSpecifier::Super:
- break;
- }
+ NestedNameSpecifier NNS = Qualifier.getNestedNameSpecifier();
+ switch (NNS.getKind()) {
+ case NestedNameSpecifier::Kind::Namespace: {
+ auto [Namespace, Prefix] = Qualifier.castAsNamespaceAndPrefix();
+ if (VisitNestedNameSpecifierLoc(Prefix))
+ return true;
+ return Visit(
+ MakeCursorNamespaceRef(Namespace, Qualifier.getLocalBeginLoc(), TU));
}
-
- return false;
+ case NestedNameSpecifier::Kind::Type:
+ return Visit(Qualifier.castAsTypeLoc());
+ case NestedNameSpecifier::Kind::Null:
+ case NestedNameSpecifier::Kind::Global:
+ case NestedNameSpecifier::Kind::Super:
+ return false;
+ }
+ llvm_unreachable("unexpected nested name specifier kind");
}
bool CursorVisitor::VisitTemplateParameters(
@@ -1526,16 +1461,23 @@ bool CursorVisitor::VisitTemplateParameters(
return false;
}
-bool CursorVisitor::VisitTemplateName(TemplateName Name, SourceLocation Loc) {
+bool CursorVisitor::VisitTemplateName(TemplateName Name, SourceLocation NameLoc,
+ NestedNameSpecifierLoc NNS) {
switch (Name.getKind()) {
+ case TemplateName::QualifiedTemplate: {
+ const QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName();
+ assert(QTN->getQualifier() == NNS.getNestedNameSpecifier());
+ if (VisitNestedNameSpecifierLoc(NNS))
+ return true;
+ return VisitTemplateName(QTN->getUnderlyingTemplate(), NameLoc, /*NNS=*/{});
+ }
case TemplateName::Template:
case TemplateName::UsingTemplate:
- case TemplateName::QualifiedTemplate: // FIXME: Visit nested-name-specifier.
- return Visit(MakeCursorTemplateRef(Name.getAsTemplateDecl(), Loc, TU));
+ return Visit(MakeCursorTemplateRef(Name.getAsTemplateDecl(), NameLoc, TU));
case TemplateName::OverloadedTemplate:
// Visit the overloaded template set.
- if (Visit(MakeCursorOverloadedDeclRef(Name, Loc, TU)))
+ if (Visit(MakeCursorOverloadedDeclRef(Name, NameLoc, TU)))
return true;
return false;
@@ -1544,17 +1486,19 @@ bool CursorVisitor::VisitTemplateName(TemplateName Name, SourceLocation Loc) {
// FIXME: Visit DeclarationName?
return false;
- case TemplateName::DependentTemplate:
- // FIXME: Visit nested-name-specifier.
- return false;
+ case TemplateName::DependentTemplate: {
+ assert(Name.getAsDependentTemplateName()->getQualifier() ==
+ NNS.getNestedNameSpecifier());
+ return VisitNestedNameSpecifierLoc(NNS);
+ }
case TemplateName::SubstTemplateTemplateParm:
return Visit(MakeCursorTemplateRef(
- Name.getAsSubstTemplateTemplateParm()->getParameter(), Loc, TU));
+ Name.getAsSubstTemplateTemplateParm()->getParameter(), NameLoc, TU));
case TemplateName::SubstTemplateTemplateParmPack:
return Visit(MakeCursorTemplateRef(
- Name.getAsSubstTemplateTemplateParmPack()->getParameterPack(), Loc,
+ Name.getAsSubstTemplateTemplateParmPack()->getParameterPack(), NameLoc,
TU));
case TemplateName::DeducedTemplate:
@@ -1598,11 +1542,9 @@ bool CursorVisitor::VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL) {
case TemplateArgument::Template:
case TemplateArgument::TemplateExpansion:
- if (VisitNestedNameSpecifierLoc(TAL.getTemplateQualifierLoc()))
- return true;
-
return VisitTemplateName(TAL.getArgument().getAsTemplateOrTemplatePattern(),
- TAL.getTemplateNameLoc());
+ TAL.getTemplateNameLoc(),
+ TAL.getTemplateQualifierLoc());
}
llvm_unreachable("Invalid TemplateArgument::Kind!");
@@ -1680,18 +1622,27 @@ bool CursorVisitor::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
}
bool CursorVisitor::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
- return Visit(MakeCursorTypeRef(TL.getTypedefNameDecl(), TL.getNameLoc(), TU));
+ if (VisitNestedNameSpecifierLoc(TL.getQualifierLoc()))
+ return true;
+
+ return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU));
}
bool CursorVisitor::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {
+ if (VisitNestedNameSpecifierLoc(TL.getQualifierLoc()))
+ return true;
+
return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU));
}
bool CursorVisitor::VisitTagTypeLoc(TagTypeLoc TL) {
+ if (VisitNestedNameSpecifierLoc(TL.getQualifierLoc()))
+ return true;
+
if (TL.isDefinition())
- return Visit(MakeCXCursor(TL.getDecl(), TU, RegionOfInterest));
+ return Visit(MakeCXCursor(TL.getOriginalDecl(), TU, RegionOfInterest));
- return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU));
+ return Visit(MakeCursorTypeRef(TL.getOriginalDecl(), TL.getNameLoc(), TU));
}
bool CursorVisitor::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
@@ -1770,7 +1721,10 @@ bool CursorVisitor::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
}
bool CursorVisitor::VisitUsingTypeLoc(UsingTypeLoc TL) {
- auto *underlyingDecl = TL.getUnderlyingType()->getAsTagDecl();
+ if (VisitNestedNameSpecifierLoc(TL.getQualifierLoc()))
+ return true;
+
+ auto *underlyingDecl = TL.getTypePtr()->desugar()->getAsTagDecl();
if (underlyingDecl) {
return Visit(MakeCursorTypeRef(underlyingDecl, TL.getNameLoc(), TU));
}
@@ -1833,7 +1787,7 @@ bool CursorVisitor::VisitAdjustedTypeLoc(AdjustedTypeLoc TL) {
bool CursorVisitor::VisitDeducedTemplateSpecializationTypeLoc(
DeducedTemplateSpecializationTypeLoc TL) {
if (VisitTemplateName(TL.getTypePtr()->getTemplateName(),
- TL.getTemplateNameLoc()))
+ TL.getTemplateNameLoc(), TL.getQualifierLoc()))
return true;
return false;
@@ -1843,7 +1797,7 @@ bool CursorVisitor::VisitTemplateSpecializationTypeLoc(
TemplateSpecializationTypeLoc TL) {
// Visit the template name.
if (VisitTemplateName(TL.getTypePtr()->getTemplateName(),
- TL.getTemplateNameLoc()))
+ TL.getTemplateNameLoc(), TL.getQualifierLoc()))
return true;
// Visit the template arguments.
@@ -1878,8 +1832,7 @@ bool CursorVisitor::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
bool CursorVisitor::VisitDependentTemplateSpecializationTypeLoc(
DependentTemplateSpecializationTypeLoc TL) {
- // Visit the nested-name-specifier, if there is one.
- if (TL.getQualifierLoc() && VisitNestedNameSpecifierLoc(TL.getQualifierLoc()))
+ if (VisitNestedNameSpecifierLoc(TL.getQualifierLoc()))
return true;
// Visit the template arguments.
@@ -1890,13 +1843,6 @@ bool CursorVisitor::VisitDependentTemplateSpecializationTypeLoc(
return false;
}
-bool CursorVisitor::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
- if (VisitNestedNameSpecifierLoc(TL.getQualifierLoc()))
- return true;
-
- return Visit(TL.getNamedTypeLoc());
-}
-
bool CursorVisitor::VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL) {
return Visit(TL.getPatternLoc());
}
@@ -1915,7 +1861,7 @@ bool CursorVisitor::VisitPackIndexingTypeLoc(PackIndexingTypeLoc TL) {
}
bool CursorVisitor::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) {
- return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU));
+ return Visit(MakeCursorTypeRef(TL.getOriginalDecl(), TL.getNameLoc(), TU));
}
bool CursorVisitor::VisitAtomicTypeLoc(AtomicTypeLoc TL) {
@@ -2072,7 +2018,7 @@ class NestedNameSpecifierLocVisit : public VisitorJob {
public:
NestedNameSpecifierLocVisit(NestedNameSpecifierLoc Qualifier, CXCursor parent)
: VisitorJob(parent, VisitorJob::NestedNameSpecifierLocVisitKind,
- Qualifier.getNestedNameSpecifier(),
+ Qualifier.getNestedNameSpecifier().getAsVoidPointer(),
Qualifier.getOpaqueData()) {}
static bool classof(const VisitorJob *VJ) {
@@ -2081,8 +2027,7 @@ class NestedNameSpecifierLocVisit : public VisitorJob {
NestedNameSpecifierLoc get() const {
return NestedNameSpecifierLoc(
- const_cast<NestedNameSpecifier *>(
- static_cast<const NestedNameSpecifier *>(data[0])),
+ NestedNameSpecifier::getFromVoidPointer(data[0]),
const_cast<void *>(data[1]));
}
};
@@ -5367,9 +5312,13 @@ CXString clang_getCursorSpelling(CXCursor C) {
case CXCursor_TypeRef: {
const TypeDecl *Type = getCursorTypeRef(C).first;
assert(Type && "Missing type decl");
+ const ASTContext &Ctx = getCursorContext(C);
+ QualType T = Ctx.getTypeDeclType(Type);
- return cxstring::createDup(
- getCursorContext(C).getTypeDeclType(Type).getAsString());
+ PrintingPolicy Policy = Ctx.getPrintingPolicy();
+ Policy.FullyQualifiedName = true;
+ Policy.SuppressTagKeyword = false;
+ return cxstring::createDup(T.getAsString(Policy));
}
case CXCursor_TemplateRef: {
const TemplateDecl *Template = getCursorTemplateRef(C).first;
diff --git a/clang/tools/libclang/CIndexCodeCompletion.cpp b/clang/tools/libclang/CIndexCodeCompletion.cpp
index 8f6729b83ffa0..1636e1e5e0a7b 100644
--- a/clang/tools/libclang/CIndexCodeCompletion.cpp
+++ b/clang/tools/libclang/CIndexCodeCompletion.cpp
@@ -616,7 +616,7 @@ namespace {
if (!baseType.isNull()) {
// Get the declaration for a class/struct/union/enum type
if (const TagType *Tag = baseType->getAs<TagType>())
- D = Tag->getDecl();
+ D = Tag->getOriginalDecl();
// Get the @interface declaration for a (possibly-qualified) Objective-C
// object pointer type, e.g., NSString*
else if (const ObjCObjectPointerType *ObjPtr =
@@ -628,7 +628,7 @@ namespace {
// Get the class for a C++ injected-class-name
else if (const InjectedClassNameType *Injected =
baseType->getAs<InjectedClassNameType>())
- D = Injected->getDecl();
+ D = Injected->getOriginalDecl();
}
if (D != nullptr) {
diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp
index a6301daa672c3..3c4062410eac1 100644
--- a/clang/tools/libclang/CXCursor.cpp
+++ b/clang/tools/libclang/CXCursor.cpp
@@ -1332,16 +1332,10 @@ CXCursor cxcursor::getTypeRefCursor(CXCursor cursor) {
TypeLoc TL = Type->getTypeLoc();
SourceLocation Loc = TL.getBeginLoc();
- if (const ElaboratedType *ElabT = Ty->getAs<ElaboratedType>()) {
- Ty = ElabT->getNamedType();
- ElaboratedTypeLoc ElabTL = TL.castAs<ElaboratedTypeLoc>();
- Loc = ElabTL.getNamedTypeLoc().getBeginLoc();
- }
-
if (const TypedefType *Typedef = Ty->getAs<TypedefType>())
return MakeCursorTypeRef(Typedef->getDecl(), Loc, TU);
if (const TagType *Tag = Ty->getAs<TagType>())
- return MakeCursorTypeRef(Tag->getDecl(), Loc, TU);
+ return MakeCursorTypeRef(Tag->getOriginalDecl(), Loc, TU);
if (const TemplateTypeParmType *TemplP = Ty->getAs<TemplateTypeParmType>())
return MakeCursorTypeRef(TemplP->getDecl(), Loc, TU);
diff --git a/clang/tools/libclang/CXIndexDataConsumer.cpp b/clang/tools/libclang/CXIndexDataConsumer.cpp
index f0d92e8c40124..941e39a582758 100644
--- a/clang/tools/libclang/CXIndexDataConsumer.cpp
+++ b/clang/tools/libclang/CXIndexDataConsumer.cpp
@@ -357,7 +357,7 @@ CXIndexDataConsumer::CXXBasesListInfo::CXXBasesListInfo(const CXXRecordDecl *D,
TST = T->getAs<TemplateSpecializationType>()) {
BaseD = TST->getTemplateName().getAsTemplateDecl();
} else if (const RecordType *RT = T->getAs<RecordType>()) {
- BaseD = RT->getDecl();
+ BaseD = RT->getOriginalDecl();
}
if (BaseD)
@@ -389,13 +389,22 @@ SourceLocation CXIndexDataConsumer::CXXBasesListInfo::getBaseLoc(
if (QualifiedTypeLoc QL = TL.getAs<QualifiedTypeLoc>())
TL = QL.getUnqualifiedLoc();
- if (ElaboratedTypeLoc EL = TL.getAs<ElaboratedTypeLoc>())
- return EL.getNamedTypeLoc().getBeginLoc();
- if (DependentNameTypeLoc DL = TL.getAs<DependentNameTypeLoc>())
- return DL.getNameLoc();
- if (DependentTemplateSpecializationTypeLoc DTL =
- TL.getAs<DependentTemplateSpecializationTypeLoc>())
- return DTL.getTemplateNameLoc();
+ // FIXME: Factor this out, a lot of TypeLoc users seem to need a generic
+ // TypeLoc::getNameLoc()
+ if (auto TTL = TL.getAs<DependentNameTypeLoc>())
+ return TTL.getNameLoc();
+ if (auto TTL = TL.getAs<DependentTemplateSpecializationTypeLoc>())
+ return TTL.getTemplateNameLoc();
+ if (auto TTL = TL.getAs<TemplateSpecializationTypeLoc>())
+ return TTL.getTemplateNameLoc();
+ if (auto TTL = TL.getAs<TagTypeLoc>())
+ return TTL.getNameLoc();
+ if (auto TTL = TL.getAs<TypedefTypeLoc>())
+ return TTL.getNameLoc();
+ if (auto TTL = TL.getAs<UnresolvedUsingTypeLoc>())
+ return TTL.getNameLoc();
+ if (auto TTL = TL.getAs<UsingTypeLoc>())
+ return TTL.getNameLoc();
return Loc;
}
diff --git a/clang/tools/libclang/CXType.cpp b/clang/tools/libclang/CXType.cpp
index e7864e6d62e4d..11d02d8088918 100644
--- a/clang/tools/libclang/CXType.cpp
+++ b/clang/tools/libclang/CXType.cpp
@@ -118,7 +118,6 @@ static CXTypeKind GetTypeKind(QualType T) {
TKCASE(ExtVector);
TKCASE(MemberPointer);
TKCASE(Auto);
- TKCASE(Elaborated);
TKCASE(Pipe);
TKCASE(Attributed);
TKCASE(BTFTagAttributed);
@@ -225,6 +224,11 @@ FindTemplateArgumentTypeAt(ArrayRef<TemplateArgument> TA, unsigned index) {
return std::nullopt;
}
+static CXType getTypeDeclType(const ASTContext &Context, CXTranslationUnit TU,
+ const TypeDecl *TD) {
+ return MakeCXType(Context.getTypeDeclType(TD), TU);
+}
+
CXType clang_getCursorType(CXCursor C) {
using namespace cxcursor;
@@ -244,7 +248,7 @@ CXType clang_getCursorType(CXCursor C) {
return MakeCXType(QualType(), TU);
if (const TypeDecl *TD = dyn_cast<TypeDecl>(D))
- return MakeCXType(Context.getTypeDeclType(TD), TU);
+ return getTypeDeclType(Context, TU, TD);
if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D))
return MakeCXType(Context.getObjCInterfaceType(ID), TU);
if (const DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D))
@@ -271,11 +275,8 @@ CXType clang_getCursorType(CXCursor C) {
return MakeCXType(T, TU);
}
- case CXCursor_TypeRef: {
- QualType T = Context.getTypeDeclType(getCursorTypeRef(C).first);
- return MakeCXType(T, TU);
-
- }
+ case CXCursor_TypeRef:
+ return getTypeDeclType(Context, TU, getCursorTypeRef(C).first);
case CXCursor_CXXBaseSpecifier:
return cxtype::MakeCXType(getCursorCXXBaseSpecifier(C)->getType(), TU);
@@ -545,11 +546,11 @@ CXCursor clang_getTypeDeclaration(CXType CT) {
break;
case Type::Record:
case Type::Enum:
- D = cast<TagType>(TP)->getDecl();
+ D = cast<TagType>(TP)->getOriginalDecl();
break;
case Type::TemplateSpecialization:
if (const RecordType *Record = TP->getAs<RecordType>())
- D = Record->getDecl();
+ D = Record->getOriginalDecl();
else
D = cast<TemplateSpecializationType>(TP)->getTemplateName()
.getAsTemplateDecl();
@@ -563,14 +564,10 @@ CXCursor clang_getTypeDeclaration(CXType CT) {
break;
case Type::InjectedClassName:
- D = cast<InjectedClassNameType>(TP)->getDecl();
+ D = cast<InjectedClassNameType>(TP)->getOriginalDecl();
break;
- // FIXME: Template type parameters!
-
- case Type::Elaborated:
- TP = cast<ElaboratedType>(TP)->getNamedType().getTypePtrOrNull();
- goto try_again;
+ // FIXME: Template type parameters!
default:
break;
@@ -990,7 +987,7 @@ CXType clang_Type_getClassType(CXType CT) {
const Type *TP = T.getTypePtrOrNull();
if (TP && TP->getTypeClass() == Type::MemberPointer) {
- ET = Ctx.getTypeDeclType(
+ ET = Ctx.getCanonicalTagType(
cast<MemberPointerType>(TP)->getMostRecentCXXRecordDecl());
}
return MakeCXType(ET, GetTU(CT));
@@ -1040,7 +1037,7 @@ static long long visitRecordForValidation(const RecordDecl *RD) {
return CXTypeLayoutError_Dependent;
// recurse
if (const RecordType *ChildType = I->getType()->getAs<RecordType>()) {
- if (const RecordDecl *Child = ChildType->getDecl()) {
+ if (const RecordDecl *Child = ChildType->getOriginalDecl()) {
long long ret = visitRecordForValidation(Child);
if (ret < 0)
return ret;
@@ -1390,10 +1387,9 @@ unsigned clang_Cursor_isInlineNamespace(CXCursor C) {
CXType clang_Type_getNamedType(CXType CT){
QualType T = GetQualType(CT);
- const Type *TP = T.getTypePtrOrNull();
- if (TP && TP->getTypeClass() == Type::Elaborated)
- return MakeCXType(cast<ElaboratedType>(TP)->getNamedType(), GetTU(CT));
+ if (!T.isNull() && T->getPrefix())
+ return MakeCXType(T, GetTU(CT));
return MakeCXType(QualType(), GetTU(CT));
}
diff --git a/clang/tools/libclang/CursorVisitor.h b/clang/tools/libclang/CursorVisitor.h
index 949b73908c315..d5ab699756988 100644
--- a/clang/tools/libclang/CursorVisitor.h
+++ b/clang/tools/libclang/CursorVisitor.h
@@ -255,12 +255,12 @@ class CursorVisitor : public DeclVisitor<CursorVisitor, bool>,
// Name visitor
bool VisitDeclarationNameInfo(DeclarationNameInfo Name);
- bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS, SourceRange Range);
bool VisitNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
// Template visitors
bool VisitTemplateParameters(const TemplateParameterList *Params);
- bool VisitTemplateName(TemplateName Name, SourceLocation Loc);
+ bool VisitTemplateName(TemplateName Name, SourceLocation NameLoc,
+ NestedNameSpecifierLoc NNS);
bool VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL);
// Type visitors
More information about the llvm-branch-commits
mailing list