mizvekov updated this revision to Diff 460910. 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 @@ -3435,25 +3435,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()) + *reinterpret_cast<QualType *>(this + 1) = 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()) + *reinterpret_cast<QualType *>(this + 1) = 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 @@ -531,6 +531,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 { @@ -4636,34 +4636,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; @@ -1885,6 +1903,8 @@ ConstantArrayTypeBitfields ConstantArrayTypeBits; AttributedTypeBitfields AttributedTypeBits; AutoTypeBitfields AutoTypeBits; + TypedefBitfields TypedefBits; + UsingBitfields UsingBits; BuiltinTypeBitfields BuiltinTypeBits; FunctionTypeBitfields FunctionTypeBits; ObjCObjectTypeBitfields ObjCObjectTypeBits; @@ -4461,42 +4481,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 cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits