Skip to content

Commit ab9eb08

Browse files
committed
meat and potatoes
1 parent 0c28482 commit ab9eb08

File tree

10 files changed

+99
-48
lines changed

10 files changed

+99
-48
lines changed

clang/include/clang/AST/Decl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3915,6 +3915,10 @@ class TagDecl : public TypeDecl,
39153915
bool isUnion() const { return getTagKind() == TagTypeKind::Union; }
39163916
bool isEnum() const { return getTagKind() == TagTypeKind::Enum; }
39173917

3918+
bool isStructureOrClass() const {
3919+
return isStruct() || isClass() || isInterface();
3920+
}
3921+
39183922
/// Is this tag type named, either directly or via being defined in
39193923
/// a typedef of this type?
39203924
///

clang/include/clang/AST/Type.h

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2883,14 +2883,21 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
28832883
/// because the type is a RecordType or because it is the injected-class-name
28842884
/// type of a class template or class template partial specialization.
28852885
CXXRecordDecl *getAsCXXRecordDecl() const;
2886+
CXXRecordDecl *castAsCXXRecordDecl() const;
28862887

28872888
/// Retrieves the RecordDecl this type refers to.
28882889
RecordDecl *getAsRecordDecl() const;
2890+
RecordDecl *castAsRecordDecl() const;
2891+
2892+
/// Retrieves the EnumDecl this type refers to.
2893+
EnumDecl *getAsEnumDecl() const;
2894+
EnumDecl *castAsEnumDecl() const;
28892895

28902896
/// Retrieves the TagDecl that this type refers to, either
28912897
/// because the type is a TagType or because it is the injected-class-name
28922898
/// type of a class template or class template partial specialization.
28932899
TagDecl *getAsTagDecl() const;
2900+
TagDecl *castAsTagDecl() const;
28942901

28952902
/// If this is a pointer or reference to a RecordType, return the
28962903
/// CXXRecordDecl that the type refers to.
@@ -2922,8 +2929,31 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
29222929
///
29232930
/// There are some specializations of this member template listed
29242931
/// immediately following this class.
2932+
///
2933+
/// If you are interested only in the canonical properties of this type,
2934+
/// consider using getAsCanonical instead, as that is much faster.
29252935
template <typename T> const T *getAs() const;
29262936

2937+
/// If this type is canonically the specified type, return its canonical type
2938+
/// cast to that specified type, otherwise returns null.
2939+
template <typename T> const T *getAsCanonical() const {
2940+
return dyn_cast<T>(CanonicalType);
2941+
}
2942+
2943+
/// Return this type's canonical type cast to the specified type.
2944+
/// If the type is not canonically that specified type, the behaviour is
2945+
/// undefined.
2946+
template <typename T> const T *castAsCanonical() const {
2947+
return cast<T>(CanonicalType);
2948+
}
2949+
2950+
// It is not helpful to use these on types which are never canonical
2951+
#define TYPE(Class, Base)
2952+
#define NEVER_CANONICAL_TYPE(Class) \
2953+
template <> inline const Class##Type *Type::getAsCanonical() const = delete; \
2954+
template <> inline const Class##Type *Type::castAsCanonical() const = delete;
2955+
#include "clang/AST/TypeNodes.inc"
2956+
29272957
/// Look through sugar for an instance of TemplateSpecializationType which
29282958
/// is not a type alias, or null if there is no such type.
29292959
/// This is used when you want as-written template arguments or the template
@@ -3135,16 +3165,16 @@ template <> const BoundsAttributedType *Type::getAs() const;
31353165
/// sugar until it reaches an CountAttributedType or a non-sugared type.
31363166
template <> const CountAttributedType *Type::getAs() const;
31373167

3138-
// We can do canonical leaf types faster, because we don't have to
3139-
// worry about preserving child type decoration.
3168+
// We can do always canonical types faster, because we don't have to
3169+
// worry about preserving decoration.
31403170
#define TYPE(Class, Base)
3141-
#define LEAF_TYPE(Class) \
3142-
template <> inline const Class##Type *Type::getAs() const { \
3143-
return dyn_cast<Class##Type>(CanonicalType); \
3144-
} \
3145-
template <> inline const Class##Type *Type::castAs() const { \
3146-
return cast<Class##Type>(CanonicalType); \
3147-
}
3171+
#define ALWAYS_CANONICAL_TYPE(Class) \
3172+
template <> inline const Class##Type *Type::getAs() const { \
3173+
return dyn_cast<Class##Type>(CanonicalType); \
3174+
} \
3175+
template <> inline const Class##Type *Type::castAs() const { \
3176+
return cast<Class##Type>(CanonicalType); \
3177+
}
31483178
#include "clang/AST/TypeNodes.inc"
31493179

31503180
/// This class is used for builtin types like 'int'. Builtin

clang/include/clang/Basic/TypeNodes.td

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -37,21 +37,12 @@ class NeverCanonical {}
3737
/// canonical types can ignore these nodes.
3838
class NeverCanonicalUnlessDependent {}
3939

40-
/// A type node which never has component type structure. Some code may be
41-
/// able to operate on leaf types faster than they can on non-leaf types.
42-
///
43-
/// For example, the function type `void (int)` is not a leaf type because it
44-
/// is structurally composed of component types (`void` and `int`).
45-
///
46-
/// A struct type is a leaf type because its field types are not part of its
47-
/// type-expression.
48-
///
49-
/// Nodes like `TypedefType` which are syntactically leaves but can desugar
50-
/// to types that may not be leaves should not declare this.
51-
class LeafType {}
40+
/// A type node which is always a canonical type, that is, types for which
41+
/// `T.getCanonicalType() == T` always holds.
42+
class AlwaysCanonical {}
5243

5344
def Type : TypeNode<?, 1>;
54-
def BuiltinType : TypeNode<Type>, LeafType;
45+
def BuiltinType : TypeNode<Type>, AlwaysCanonical;
5546
def ComplexType : TypeNode<Type>;
5647
def PointerType : TypeNode<Type>;
5748
def BlockPointerType : TypeNode<Type>;
@@ -88,14 +79,14 @@ def TypeOfType : TypeNode<Type>, NeverCanonicalUnlessDependent;
8879
def DecltypeType : TypeNode<Type>, NeverCanonicalUnlessDependent;
8980
def UnaryTransformType : TypeNode<Type>, NeverCanonicalUnlessDependent;
9081
def TagType : TypeNode<Type, 1>;
91-
def RecordType : TypeNode<TagType>, LeafType;
92-
def EnumType : TypeNode<TagType>, LeafType;
93-
def InjectedClassNameType : TypeNode<TagType>, AlwaysDependent, LeafType;
82+
def RecordType : TypeNode<TagType>;
83+
def EnumType : TypeNode<TagType>;
84+
def InjectedClassNameType : TypeNode<TagType>, AlwaysDependent;
9485
def AttributedType : TypeNode<Type>, NeverCanonical;
9586
def BTFTagAttributedType : TypeNode<Type>, NeverCanonical;
9687
def HLSLAttributedResourceType : TypeNode<Type>;
9788
def HLSLInlineSpirvType : TypeNode<Type>;
98-
def TemplateTypeParmType : TypeNode<Type>, AlwaysDependent, LeafType;
89+
def TemplateTypeParmType : TypeNode<Type>, AlwaysDependent;
9990
def SubstTemplateTypeParmType : TypeNode<Type>, NeverCanonical;
10091
def SubstPackType : TypeNode<Type, 1>;
10192
def SubstTemplateTypeParmPackType : TypeNode<SubstPackType>, AlwaysDependent;
@@ -110,7 +101,7 @@ def PackExpansionType : TypeNode<Type>, AlwaysDependent;
110101
def PackIndexingType : TypeNode<Type>, NeverCanonicalUnlessDependent;
111102
def ObjCTypeParamType : TypeNode<Type>, NeverCanonical;
112103
def ObjCObjectType : TypeNode<Type>;
113-
def ObjCInterfaceType : TypeNode<ObjCObjectType>, LeafType;
104+
def ObjCInterfaceType : TypeNode<ObjCObjectType>, AlwaysCanonical;
114105
def ObjCObjectPointerType : TypeNode<Type>;
115106
def BoundsAttributedType : TypeNode<Type, 1>;
116107
def CountAttributedType : TypeNode<BoundsAttributedType>, NeverCanonical;

clang/include/clang/Sema/Sema.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5404,7 +5404,7 @@ class Sema final : public SemaBase {
54045404

54055405
/// FinalizeVarWithDestructor - Prepare for calling destructor on the
54065406
/// constructed variable.
5407-
void FinalizeVarWithDestructor(VarDecl *VD, const RecordType *DeclInitType);
5407+
void FinalizeVarWithDestructor(VarDecl *VD, CXXRecordDecl *DeclInit);
54085408

54095409
/// Helper class that collects exception specifications for
54105410
/// implicitly-declared special member functions.

clang/lib/AST/Type.cpp

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -708,10 +708,8 @@ bool Type::isInterfaceType() const {
708708
}
709709

710710
bool Type::isStructureOrClassType() const {
711-
if (const auto *RT = getAs<RecordType>()) {
712-
RecordDecl *RD = RT->getOriginalDecl();
713-
return RD->isStruct() || RD->isClass() || RD->isInterface();
714-
}
711+
if (const auto *RT = getAsCanonical<RecordType>())
712+
return RT->getOriginalDecl()->isStructureOrClass();
715713
return false;
716714
}
717715

@@ -1938,19 +1936,45 @@ CXXRecordDecl *Type::getAsCXXRecordDecl() const {
19381936
return cast<CXXRecordDecl>(TD)->getDefinitionOrSelf();
19391937
}
19401938

1939+
CXXRecordDecl *Type::castAsCXXRecordDecl() const {
1940+
const auto *TT = cast<TagType>(CanonicalType);
1941+
return cast<CXXRecordDecl>(TT->getOriginalDecl())->getDefinitionOrSelf();
1942+
}
1943+
19411944
RecordDecl *Type::getAsRecordDecl() const {
19421945
const auto *TT = dyn_cast<TagType>(CanonicalType);
19431946
if (!isa_and_present<RecordType, InjectedClassNameType>(TT))
19441947
return nullptr;
19451948
return cast<RecordDecl>(TT->getOriginalDecl())->getDefinitionOrSelf();
19461949
}
19471950

1951+
RecordDecl *Type::castAsRecordDecl() const {
1952+
const auto *TT = cast<TagType>(CanonicalType);
1953+
return cast<RecordDecl>(TT->getOriginalDecl())->getDefinitionOrSelf();
1954+
}
1955+
1956+
EnumDecl *Type::getAsEnumDecl() const {
1957+
if (const auto *TT = dyn_cast<EnumType>(CanonicalType))
1958+
return TT->getOriginalDecl()->getDefinitionOrSelf();
1959+
return nullptr;
1960+
}
1961+
1962+
EnumDecl *Type::castAsEnumDecl() const {
1963+
return cast<EnumType>(CanonicalType)
1964+
->getOriginalDecl()
1965+
->getDefinitionOrSelf();
1966+
}
1967+
19481968
TagDecl *Type::getAsTagDecl() const {
19491969
if (const auto *TT = dyn_cast<TagType>(CanonicalType))
19501970
return TT->getOriginalDecl()->getDefinitionOrSelf();
19511971
return nullptr;
19521972
}
19531973

1974+
TagDecl *Type::castAsTagDecl() const {
1975+
return cast<TagType>(CanonicalType)->getOriginalDecl()->getDefinitionOrSelf();
1976+
}
1977+
19541978
const TemplateSpecializationType *
19551979
Type::getAsNonAliasTemplateSpecializationType() const {
19561980
const auto *TST = getAs<TemplateSpecializationType>();

clang/test/CXX/drs/cwg0xx.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ namespace cwg16 { // cwg16: 2.8
244244
// expected-error@#cwg16-A-f-call {{'A' is a private member of 'cwg16::A'}}
245245
// expected-note@#cwg16-B {{constrained by implicitly private inheritance here}}
246246
// expected-note@#cwg16-A {{member is declared here}}
247-
// expected-error@#cwg16-A-f-call {{cannot cast 'cwg16::C' to its private base class 'cwg16::A'}}
247+
// expected-error@#cwg16-A-f-call {{cannot cast 'cwg16::C' to its private base class 'A'}}
248248
// expected-note@#cwg16-B {{implicitly declared private here}}
249249
}
250250
};
@@ -838,7 +838,7 @@ namespace cwg52 { // cwg52: 2.8
838838
// expected-error@#cwg52-k {{'A' is a private member of 'cwg52::A'}}
839839
// expected-note@#cwg52-B {{constrained by private inheritance here}}
840840
// expected-note@#cwg52-A {{member is declared here}}
841-
// expected-error@#cwg52-k {{cannot cast 'struct B' to its private base class 'cwg52::A'}}
841+
// expected-error@#cwg52-k {{cannot cast 'struct B' to its private base class 'A'}}
842842
// expected-note@#cwg52-B {{declared private here}}
843843
} // namespace cwg52
844844

clang/test/CXX/drs/cwg3xx.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1321,7 +1321,7 @@ namespace cwg381 { // cwg381: 2.7
13211321
void f() {
13221322
E e;
13231323
e.B::a = 0;
1324-
/* expected-error@-1 {{ambiguous conversion from derived class 'E' to base class 'cwg381::B':
1324+
/* expected-error@-1 {{ambiguous conversion from derived class 'E' to base class 'B':
13251325
struct cwg381::E -> C -> B
13261326
struct cwg381::E -> D -> B}} */
13271327
F f;

clang/test/ExtractAPI/class_template_param_inheritance.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ template<typename T> class Foo : public T {};
4444
{
4545
"kind": "inheritsFrom",
4646
"source": "c:@ST>1#T@Foo",
47-
"target": "",
47+
"target": "c:input.h@9",
4848
"targetFallback": "T"
4949
}
5050
],

clang/utils/TableGen/ASTTableGen.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
#define AlwaysDependentClassName "AlwaysDependent"
3939
#define NeverCanonicalClassName "NeverCanonical"
4040
#define NeverCanonicalUnlessDependentClassName "NeverCanonicalUnlessDependent"
41-
#define LeafTypeClassName "LeafType"
41+
#define AlwaysCanonicalTypeClassName "AlwaysCanonical"
4242

4343
// Cases of various non-ASTNode structured types like DeclarationName.
4444
#define TypeKindClassName "PropertyTypeKind"

clang/utils/TableGen/ClangTypeNodesEmitter.cpp

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,9 @@
4040
// There is a sixth macro, independent of the others. Most clients
4141
// will not need to use it.
4242
//
43-
// LEAF_TYPE(Class) - A type that never has inner types. Clients
44-
// which can operate on such types more efficiently may wish to do so.
43+
// ALWAYS_CANONICAL_TYPE(Class) - A type which is always identical to its
44+
// canonical type. Clients which can operate on such types more efficiently
45+
// may wish to do so.
4546
//
4647
//===----------------------------------------------------------------------===//
4748

@@ -66,7 +67,7 @@ using namespace clang::tblgen;
6667
#define NonCanonicalUnlessDependentTypeMacroName "NON_CANONICAL_UNLESS_DEPENDENT_TYPE"
6768
#define TypeMacroArgs "(Class, Base)"
6869
#define LastTypeMacroName "LAST_TYPE"
69-
#define LeafTypeMacroName "LEAF_TYPE"
70+
#define AlwaysCanonicalTypeMacroName "ALWAYS_CANONICAL_TYPE"
7071

7172
#define TypeClassName "Type"
7273

@@ -90,7 +91,7 @@ class TypeNodeEmitter {
9091

9192
void emitNodeInvocations();
9293
void emitLastNodeInvocation(TypeNode lastType);
93-
void emitLeafNodeInvocations();
94+
void emitAlwaysCanonicalNodeInvocations();
9495

9596
void addMacroToUndef(StringRef macroName);
9697
void emitUndefs();
@@ -109,12 +110,12 @@ void TypeNodeEmitter::emit() {
109110
emitFallbackDefine(AbstractTypeMacroName, TypeMacroName, TypeMacroArgs);
110111
emitFallbackDefine(NonCanonicalTypeMacroName, TypeMacroName, TypeMacroArgs);
111112
emitFallbackDefine(DependentTypeMacroName, TypeMacroName, TypeMacroArgs);
112-
emitFallbackDefine(NonCanonicalUnlessDependentTypeMacroName, TypeMacroName,
113+
emitFallbackDefine(NonCanonicalUnlessDependentTypeMacroName, TypeMacroName,
113114
TypeMacroArgs);
114115

115116
// Invocations.
116117
emitNodeInvocations();
117-
emitLeafNodeInvocations();
118+
emitAlwaysCanonicalNodeInvocations();
118119

119120
// Postmatter
120121
emitUndefs();
@@ -178,15 +179,16 @@ void TypeNodeEmitter::emitLastNodeInvocation(TypeNode type) {
178179
"#endif\n";
179180
}
180181

181-
void TypeNodeEmitter::emitLeafNodeInvocations() {
182-
Out << "#ifdef " LeafTypeMacroName "\n";
182+
void TypeNodeEmitter::emitAlwaysCanonicalNodeInvocations() {
183+
Out << "#ifdef " AlwaysCanonicalTypeMacroName "\n";
183184

184185
for (TypeNode type : Types) {
185-
if (!type.isSubClassOf(LeafTypeClassName)) continue;
186-
Out << LeafTypeMacroName "(" << type.getId() << ")\n";
186+
if (!type.isSubClassOf(AlwaysCanonicalTypeClassName))
187+
continue;
188+
Out << AlwaysCanonicalTypeMacroName "(" << type.getId() << ")\n";
187189
}
188190

189-
Out << "#undef " LeafTypeMacroName "\n"
191+
Out << "#undef " AlwaysCanonicalTypeMacroName "\n"
190192
"#endif\n";
191193
}
192194

0 commit comments

Comments
 (0)