mizvekov updated this revision to Diff 461850.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D133468/new/
https://reviews.llvm.org/D133468
Files:
clang/include/clang/AST/ASTContext.h
clang/include/clang/AST/JSONNodeDumper.h
clang/include/clang/AST/Type.h
clang/include/clang/AST/TypeProperties.td
clang/lib/AST/ASTContext.cpp
clang/lib/AST/ASTImporter.cpp
clang/lib/AST/ASTStructuralEquivalence.cpp
clang/lib/AST/JSONNodeDumper.cpp
clang/lib/AST/TextNodeDumper.cpp
clang/lib/AST/Type.cpp
clang/test/SemaCXX/sugar-common-types.cpp
Index: clang/test/SemaCXX/sugar-common-types.cpp
===================================================================
--- clang/test/SemaCXX/sugar-common-types.cpp
+++ clang/test/SemaCXX/sugar-common-types.cpp
@@ -112,3 +112,22 @@
C2<X2> auto t26_3 = (::SB1){};
N t26 = 0 ? t26_1 : t26_2; // expected-error {{from 'SB1' (aka 'SS1')}}
N t27 = 0 ? t26_1 : t26_3; // expected-error {{from 'SB1' (aka 'SS1')}}
+
+using RPB1 = X1*;
+using RPX1 = RPB1;
+using RPB1 = Y1*; // redeclared
+using RPY1 = RPB1;
+N t28 = *(RPB1){}; // expected-error {{lvalue of type 'Y1' (aka 'int')}}
+auto t29 = 0 ? (RPX1){} : (RPY1){};
+N t30 = t29; // expected-error {{lvalue of type 'RPB1' (aka 'int *')}}
+N t31 = *t29; // expected-error {{lvalue of type 'B1' (aka 'int')}}
+
+namespace A { using type1 = X1*; };
+namespace C { using A::type1; };
+using UPX1 = C::type1;
+namespace A { using type1 = Y1*; }; // redeclared
+namespace C { using A::type1; }; // redeclared
+using UPY1 = C::type1;
+auto t32 = 0 ? (UPX1){} : (UPY1){};
+N t33 = t32; // expected-error {{lvalue of type 'C::type1' (aka 'int *')}}
+N t34 = *t32; // expected-error {{lvalue of type 'B1' (aka 'int')}}
Index: clang/lib/AST/Type.cpp
===================================================================
--- clang/lib/AST/Type.cpp
+++ clang/lib/AST/Type.cpp
@@ -3434,25 +3434,34 @@
}
TypedefType::TypedefType(TypeClass tc, const TypedefNameDecl *D,
- QualType underlying, QualType can)
- : Type(tc, can, toSemanticDependence(underlying->getDependence())),
+ QualType Underlying, QualType can)
+ : Type(tc, can, toSemanticDependence(can->getDependence())),
Decl(const_cast<TypedefNameDecl *>(D)) {
assert(!isa<TypedefType>(can) && "Invalid canonical type");
+ TypedefBits.isDivergent = !Underlying.isNull();
+ if (isDivergent())
+ *getTrailingObjects<QualType>() = Underlying;
}
QualType TypedefType::desugar() const {
- return getDecl()->getUnderlyingType();
+ return isDivergent() ? *getTrailingObjects<QualType>()
+ : Decl->getUnderlyingType();
}
UsingType::UsingType(const UsingShadowDecl *Found, QualType Underlying,
QualType Canon)
- : Type(Using, Canon, toSemanticDependence(Underlying->getDependence())),
+ : Type(Using, Canon, toSemanticDependence(Canon->getDependence())),
Found(const_cast<UsingShadowDecl *>(Found)) {
- assert(Underlying == getUnderlyingType());
+ UsingBits.isDivergent = !Underlying.isNull();
+ if (isDivergent())
+ *getTrailingObjects<QualType>() = Underlying;
}
QualType UsingType::getUnderlyingType() const {
- return QualType(cast<TypeDecl>(Found->getTargetDecl())->getTypeForDecl(), 0);
+ return isDivergent()
+ ? *getTrailingObjects<QualType>()
+ : QualType(
+ cast<TypeDecl>(Found->getTargetDecl())->getTypeForDecl(), 0);
}
QualType MacroQualifiedType::desugar() const { return getUnderlyingType(); }
Index: clang/lib/AST/TextNodeDumper.cpp
===================================================================
--- clang/lib/AST/TextNodeDumper.cpp
+++ clang/lib/AST/TextNodeDumper.cpp
@@ -1543,10 +1543,14 @@
void TextNodeDumper::VisitUsingType(const UsingType *T) {
dumpDeclRef(T->getFoundDecl());
+ if (T->isDivergent())
+ OS << " divergent";
}
void TextNodeDumper::VisitTypedefType(const TypedefType *T) {
dumpDeclRef(T->getDecl());
+ if (T->isDivergent())
+ OS << " divergent";
}
void TextNodeDumper::VisitUnaryTransformType(const UnaryTransformType *T) {
Index: clang/lib/AST/JSONNodeDumper.cpp
===================================================================
--- clang/lib/AST/JSONNodeDumper.cpp
+++ clang/lib/AST/JSONNodeDumper.cpp
@@ -530,6 +530,14 @@
void JSONNodeDumper::VisitTypedefType(const TypedefType *TT) {
JOS.attribute("decl", createBareDeclRef(TT->getDecl()));
+ if (TT->isDivergent())
+ JOS.attribute("type", createQualType(TT->desugar()));
+}
+
+void JSONNodeDumper::VisitUsingType(const UsingType *TT) {
+ JOS.attribute("decl", createBareDeclRef(TT->getFoundDecl()));
+ if (TT->isDivergent())
+ JOS.attribute("type", createQualType(TT->desugar()));
}
void JSONNodeDumper::VisitFunctionType(const FunctionType *T) {
Index: clang/lib/AST/ASTStructuralEquivalence.cpp
===================================================================
--- clang/lib/AST/ASTStructuralEquivalence.cpp
+++ clang/lib/AST/ASTStructuralEquivalence.cpp
@@ -957,11 +957,17 @@
if (!IsStructurallyEquivalent(Context, cast<UsingType>(T1)->getFoundDecl(),
cast<UsingType>(T2)->getFoundDecl()))
return false;
+ if (!IsStructurallyEquivalent(Context,
+ cast<UsingType>(T1)->getUnderlyingType(),
+ cast<UsingType>(T2)->getUnderlyingType()))
+ return false;
break;
case Type::Typedef:
if (!IsStructurallyEquivalent(Context, cast<TypedefType>(T1)->getDecl(),
- cast<TypedefType>(T2)->getDecl()))
+ cast<TypedefType>(T2)->getDecl()) ||
+ !IsStructurallyEquivalent(Context, cast<TypedefType>(T1)->desugar(),
+ cast<TypedefType>(T2)->desugar()))
return false;
break;
Index: clang/lib/AST/ASTImporter.cpp
===================================================================
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -1362,8 +1362,12 @@
Expected<TypedefNameDecl *> ToDeclOrErr = import(T->getDecl());
if (!ToDeclOrErr)
return ToDeclOrErr.takeError();
+ ExpectedType ToUnderlyingTypeOrErr = import(T->desugar());
+ if (!ToUnderlyingTypeOrErr)
+ return ToUnderlyingTypeOrErr.takeError();
- return Importer.getToContext().getTypeDeclType(*ToDeclOrErr);
+ return Importer.getToContext().getTypedefType(*ToDeclOrErr,
+ *ToUnderlyingTypeOrErr);
}
ExpectedType ASTNodeImporter::VisitTypeOfExprType(const TypeOfExprType *T) {
Index: clang/lib/AST/ASTContext.cpp
===================================================================
--- clang/lib/AST/ASTContext.cpp
+++ clang/lib/AST/ASTContext.cpp
@@ -2370,12 +2370,12 @@
return getTypeInfo(cast<UsingType>(T)->desugar().getTypePtr());
case Type::Typedef: {
- const TypedefNameDecl *Typedef = cast<TypedefType>(T)->getDecl();
- TypeInfo Info = getTypeInfo(Typedef->getUnderlyingType().getTypePtr());
+ const auto *TT = cast<TypedefType>(T);
+ TypeInfo Info = getTypeInfo(TT->desugar().getTypePtr());
// If the typedef has an aligned attribute on it, it overrides any computed
// alignment we have. This violates the GCC documentation (which says that
// attribute(aligned) can only round up) but matches its implementation.
- if (unsigned AttrAlign = Typedef->getMaxAlignment()) {
+ if (unsigned AttrAlign = TT->getDecl()->getMaxAlignment()) {
Align = AttrAlign;
AlignRequirement = AlignRequirementKind::RequiredByTypedef;
} else {
@@ -4644,34 +4644,60 @@
/// specified typedef name decl.
QualType ASTContext::getTypedefType(const TypedefNameDecl *Decl,
QualType Underlying) const {
- if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0);
+ if (!Decl->TypeForDecl) {
+ if (Underlying.isNull())
+ Underlying = Decl->getUnderlyingType();
+ auto *NewType = new (*this, TypeAlignment) TypedefType(
+ Type::Typedef, Decl, QualType(), getCanonicalType(Underlying));
+ Decl->TypeForDecl = NewType;
+ Types.push_back(NewType);
+ return QualType(NewType, 0);
+ }
+ if (Underlying.isNull() || Decl->getUnderlyingType() == Underlying)
+ return QualType(Decl->TypeForDecl, 0);
+ assert(hasSameType(Decl->getUnderlyingType(), Underlying));
- if (Underlying.isNull())
- Underlying = Decl->getUnderlyingType();
- QualType Canonical = getCanonicalType(Underlying);
- auto *newType = new (*this, TypeAlignment)
- TypedefType(Type::Typedef, Decl, Underlying, Canonical);
- Decl->TypeForDecl = newType;
- Types.push_back(newType);
- return QualType(newType, 0);
+ llvm::FoldingSetNodeID ID;
+ TypedefType::Profile(ID, Decl, Underlying);
+
+ void *InsertPos = nullptr;
+ if (TypedefType *T = TypedefTypes.FindNodeOrInsertPos(ID, InsertPos)) {
+ assert(T->isDivergent() &&
+ "non-divergent case should be handled with TypeDecl");
+ return QualType(T, 0);
+ }
+
+ void *Mem =
+ Allocate(TypedefType::totalSizeToAlloc<QualType>(true), TypeAlignment);
+ auto *NewType = new (Mem) TypedefType(Type::Typedef, Decl, Underlying,
+ getCanonicalType(Underlying));
+ TypedefTypes.InsertNode(NewType, InsertPos);
+ Types.push_back(NewType);
+ return QualType(NewType, 0);
}
QualType ASTContext::getUsingType(const UsingShadowDecl *Found,
QualType Underlying) const {
llvm::FoldingSetNodeID ID;
- UsingType::Profile(ID, Found);
+ UsingType::Profile(ID, Found, Underlying);
void *InsertPos = nullptr;
- UsingType *T = UsingTypes.FindNodeOrInsertPos(ID, InsertPos);
- if (T)
+ if (UsingType *T = UsingTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(T, 0);
- assert(!Underlying.hasLocalQualifiers());
- assert(Underlying == getTypeDeclType(cast<TypeDecl>(Found->getTargetDecl())));
- QualType Canon = Underlying.getCanonicalType();
+ const Type *TypeForDecl =
+ cast<TypeDecl>(Found->getTargetDecl())->getTypeForDecl();
- UsingType *NewType =
- new (*this, TypeAlignment) UsingType(Found, Underlying, Canon);
+ assert(!Underlying.hasLocalQualifiers());
+ QualType Canon = Underlying->getCanonicalTypeInternal();
+ assert(TypeForDecl->getCanonicalTypeInternal() == Canon);
+
+ if (Underlying.getTypePtr() == TypeForDecl)
+ Underlying = QualType();
+ void *Mem =
+ Allocate(UsingType::totalSizeToAlloc<QualType>(!Underlying.isNull()),
+ TypeAlignment);
+ UsingType *NewType = new (Mem) UsingType(Found, Underlying, Canon);
Types.push_back(NewType);
UsingTypes.InsertNode(NewType, InsertPos);
return QualType(NewType, 0);
Index: clang/include/clang/AST/TypeProperties.td
===================================================================
--- clang/include/clang/AST/TypeProperties.td
+++ clang/include/clang/AST/TypeProperties.td
@@ -379,16 +379,12 @@
def : Property<"declaration", DeclRef> {
let Read = [{ node->getDecl() }];
}
- def : Property<"canonicalType", Optional<QualType>> {
- let Read = [{ makeOptionalFromNullable(node->getCanonicalTypeInternal()) }];
+ def : Property<"underlyingType", QualType> {
+ let Read = [{ node->desugar() }];
}
def : Creator<[{
- QualType finalCanonicalType =
- canonicalType ? ctx.getCanonicalType(*canonicalType)
- : QualType();
- return ctx.getTypedefType(cast<TypedefNameDecl>(declaration),
- finalCanonicalType);
+ return ctx.getTypedefType(cast<TypedefNameDecl>(declaration), underlyingType);
}]>;
}
Index: clang/include/clang/AST/Type.h
===================================================================
--- clang/include/clang/AST/Type.h
+++ clang/include/clang/AST/Type.h
@@ -1793,6 +1793,24 @@
unsigned NumArgs;
};
+ class UsingBitfields {
+ friend class UsingType;
+
+ unsigned : NumTypeBits;
+
+ /// True if the underlying diverges from the declared one.
+ unsigned isDivergent : 1;
+ };
+
+ class TypedefBitfields {
+ friend class TypedefType;
+
+ unsigned : NumTypeBits;
+
+ /// True if the underlying diverges from the declared one.
+ unsigned isDivergent : 1;
+ };
+
class SubstTemplateTypeParmTypeBitfields {
friend class SubstTemplateTypeParmType;
@@ -1880,6 +1898,8 @@
ConstantArrayTypeBitfields ConstantArrayTypeBits;
AttributedTypeBitfields AttributedTypeBits;
AutoTypeBitfields AutoTypeBits;
+ TypedefBitfields TypedefBits;
+ UsingBitfields UsingBits;
BuiltinTypeBitfields BuiltinTypeBits;
FunctionTypeBitfields FunctionTypeBits;
ObjCObjectTypeBitfields ObjCObjectTypeBits;
@@ -4456,42 +4476,62 @@
}
};
-class UsingType : public Type, public llvm::FoldingSetNode {
+class UsingType final : public Type,
+ public llvm::FoldingSetNode,
+ private llvm::TrailingObjects<UsingType, QualType> {
UsingShadowDecl *Found;
friend class ASTContext; // ASTContext creates these.
+ friend TrailingObjects;
UsingType(const UsingShadowDecl *Found, QualType Underlying, QualType Canon);
public:
UsingShadowDecl *getFoundDecl() const { return Found; }
+ bool isDivergent() const { return UsingBits.isDivergent; }
QualType getUnderlyingType() const;
bool isSugared() const { return true; }
QualType desugar() const { return getUnderlyingType(); }
- void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, Found); }
- static void Profile(llvm::FoldingSetNodeID &ID,
- const UsingShadowDecl *Found) {
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, Found, isDivergent() ? getUnderlyingType() : QualType());
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID, const UsingShadowDecl *Found,
+ QualType Underlying) {
ID.AddPointer(Found);
+ if (!Underlying.isNull())
+ Underlying.Profile(ID);
}
static bool classof(const Type *T) { return T->getTypeClass() == Using; }
};
-class TypedefType : public Type {
+class TypedefType final : public Type,
+ public llvm::FoldingSetNode,
+ private llvm::TrailingObjects<TypedefType, QualType> {
TypedefNameDecl *Decl;
-
-private:
friend class ASTContext; // ASTContext creates these.
+ friend TrailingObjects;
TypedefType(TypeClass tc, const TypedefNameDecl *D, QualType underlying,
QualType can);
public:
TypedefNameDecl *getDecl() const { return Decl; }
+ bool isDivergent() const { return TypedefBits.isDivergent; }
bool isSugared() const { return true; }
QualType desugar() const;
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, Decl, isDivergent() ? desugar() : QualType());
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID, const TypedefNameDecl *Decl,
+ QualType Underlying) {
+ ID.AddPointer(Decl);
+ if (!Underlying.isNull())
+ Underlying.Profile(ID);
+ }
+
static bool classof(const Type *T) { return T->getTypeClass() == Typedef; }
};
Index: clang/include/clang/AST/JSONNodeDumper.h
===================================================================
--- clang/include/clang/AST/JSONNodeDumper.h
+++ clang/include/clang/AST/JSONNodeDumper.h
@@ -209,6 +209,7 @@
void Visit(const APValue &Value, QualType Ty);
void VisitTypedefType(const TypedefType *TT);
+ void VisitUsingType(const UsingType *TT);
void VisitFunctionType(const FunctionType *T);
void VisitFunctionProtoType(const FunctionProtoType *T);
void VisitRValueReferenceType(const ReferenceType *RT);
Index: clang/include/clang/AST/ASTContext.h
===================================================================
--- clang/include/clang/AST/ASTContext.h
+++ clang/include/clang/AST/ASTContext.h
@@ -246,6 +246,7 @@
TemplateSpecializationTypes;
mutable llvm::FoldingSet<ParenType> ParenTypes{GeneralTypesLog2InitSize};
mutable llvm::FoldingSet<UsingType> UsingTypes;
+ mutable llvm::FoldingSet<TypedefType> TypedefTypes;
mutable llvm::FoldingSet<ElaboratedType> ElaboratedTypes{
GeneralTypesLog2InitSize};
mutable llvm::FoldingSet<DependentNameType> DependentNameTypes;
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits