From 1dbc7a7a5a4836f84d7304762ba93da34a339c52 Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Sun, 27 Mar 2016 04:46:07 +0000 Subject: [PATCH] Improve the representation of CXXUuidofExpr Keep a pointer to the UuidAttr that the CXXUuidofExpr corresponds to. This makes translating from __uuidof to the underlying constant a lot more straightforward. llvm-svn: 264529 --- clang/include/clang/AST/ExprCXX.h | 34 ++++++++--------- clang/lib/AST/ExprCXX.cpp | 73 +------------------------------------ clang/lib/AST/MicrosoftMangle.cpp | 2 +- clang/lib/CodeGen/CodeGenModule.cpp | 2 +- clang/lib/Sema/SemaExprCXX.cpp | 71 ++++++++++++++++++++++++++++-------- 5 files changed, 74 insertions(+), 108 deletions(-) diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index 2b8c0ea..af4f9e3 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -778,22 +778,23 @@ public: class CXXUuidofExpr : public Expr { private: llvm::PointerUnion Operand; + const UuidAttr *UA; SourceRange Range; public: - CXXUuidofExpr(QualType Ty, TypeSourceInfo *Operand, SourceRange R) - : Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary, - false, Operand->getType()->isDependentType(), - Operand->getType()->isInstantiationDependentType(), - Operand->getType()->containsUnexpandedParameterPack()), - Operand(Operand), Range(R) { } - - CXXUuidofExpr(QualType Ty, Expr *Operand, SourceRange R) - : Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary, - false, Operand->isTypeDependent(), - Operand->isInstantiationDependent(), - Operand->containsUnexpandedParameterPack()), - Operand(Operand), Range(R) { } + CXXUuidofExpr(QualType Ty, TypeSourceInfo *Operand, const UuidAttr *UA, + SourceRange R) + : Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary, false, + Operand->getType()->isDependentType(), + Operand->getType()->isInstantiationDependentType(), + Operand->getType()->containsUnexpandedParameterPack()), + Operand(Operand), UA(UA), Range(R) {} + + CXXUuidofExpr(QualType Ty, Expr *Operand, const UuidAttr *UA, SourceRange R) + : Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary, false, + Operand->isTypeDependent(), Operand->isInstantiationDependent(), + Operand->containsUnexpandedParameterPack()), + Operand(Operand), UA(UA), Range(R) {} CXXUuidofExpr(EmptyShell Empty, bool isExpr) : Expr(CXXUuidofExprClass, Empty) { @@ -830,7 +831,7 @@ public: Operand = E; } - StringRef getUuidAsStringRef(ASTContext &Context) const; + StringRef getUuidAsStringRef() const; SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } @@ -841,11 +842,6 @@ public: return T->getStmtClass() == CXXUuidofExprClass; } - /// Grabs __declspec(uuid()) off a type, or returns 0 if we cannot resolve to - /// a single GUID. - static const UuidAttr *GetUuidAttrOfType(QualType QT, - bool *HasMultipleGUIDsPtr = nullptr); - // Iterators child_range children() { if (isTypeOperand()) diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index b1b91f7..438a376 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -54,77 +54,8 @@ QualType CXXUuidofExpr::getTypeOperand(ASTContext &Context) const { Operand.get()->getType().getNonReferenceType(), Quals); } -// static -const UuidAttr *CXXUuidofExpr::GetUuidAttrOfType(QualType QT, - bool *RDHasMultipleGUIDsPtr) { - // Optionally remove one level of pointer, reference or array indirection. - const Type *Ty = QT.getTypePtr(); - if (QT->isPointerType() || QT->isReferenceType()) - Ty = QT->getPointeeType().getTypePtr(); - else if (QT->isArrayType()) - Ty = Ty->getBaseElementTypeUnsafe(); - - const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl(); - if (!RD) - return nullptr; - - if (const UuidAttr *Uuid = RD->getMostRecentDecl()->getAttr()) - return Uuid; - - // __uuidof can grab UUIDs from template arguments. - if (const ClassTemplateSpecializationDecl *CTSD = - dyn_cast(RD)) { - const TemplateArgumentList &TAL = CTSD->getTemplateArgs(); - const UuidAttr *UuidForRD = nullptr; - - for (const TemplateArgument &TA : TAL.asArray()) { - bool SeenMultipleGUIDs = false; - - const UuidAttr *UuidForTA = nullptr; - if (TA.getKind() == TemplateArgument::Type) - UuidForTA = GetUuidAttrOfType(TA.getAsType(), &SeenMultipleGUIDs); - else if (TA.getKind() == TemplateArgument::Declaration) - UuidForTA = - GetUuidAttrOfType(TA.getAsDecl()->getType(), &SeenMultipleGUIDs); - - // If the template argument has a UUID, there are three cases: - // - This is the first UUID seen for this RecordDecl. - // - This is a different UUID than previously seen for this RecordDecl. - // - This is the same UUID than previously seen for this RecordDecl. - if (UuidForTA) { - if (!UuidForRD) - UuidForRD = UuidForTA; - else if (UuidForRD != UuidForTA) - SeenMultipleGUIDs = true; - } - - // Seeing multiple UUIDs means that we couldn't find a UUID - if (SeenMultipleGUIDs) { - if (RDHasMultipleGUIDsPtr) - *RDHasMultipleGUIDsPtr = true; - return nullptr; - } - } - - return UuidForRD; - } - - return nullptr; -} - -StringRef CXXUuidofExpr::getUuidAsStringRef(ASTContext &Context) const { - StringRef Uuid; - if (isTypeOperand()) - Uuid = CXXUuidofExpr::GetUuidAttrOfType(getTypeOperand(Context))->getGuid(); - else { - // Special case: __uuidof(0) means an all-zero GUID. - Expr *Op = getExprOperand(); - if (!Op->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) - Uuid = CXXUuidofExpr::GetUuidAttrOfType(Op->getType())->getGuid(); - else - Uuid = "00000000-0000-0000-0000-000000000000"; - } - return Uuid; +StringRef CXXUuidofExpr::getUuidAsStringRef() const { + return UA ? UA->getGuid() : "00000000-0000-0000-0000-000000000000"; } // CXXScalarValueInitExpr diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index 2be8cec..002c220 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -1186,7 +1186,7 @@ void MicrosoftCXXNameMangler::mangleExpression(const Expr *E) { // This CXXUuidofExpr is mangled as-if it were actually a VarDecl from // const __s_GUID _GUID_{lower case UUID with underscores} - StringRef Uuid = UE->getUuidAsStringRef(Context.getASTContext()); + StringRef Uuid = UE->getUuidAsStringRef(); std::string Name = "_GUID_" + Uuid.lower(); std::replace(Name.begin(), Name.end(), '-', '_'); diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 42dc811..399b739 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1454,7 +1454,7 @@ ConstantAddress CodeGenModule::GetAddrOfUuidDescriptor( const CXXUuidofExpr* E) { // Sema has verified that IIDSource has a __declspec(uuid()), and that its // well-formed. - StringRef Uuid = E->getUuidAsStringRef(Context); + StringRef Uuid = E->getUuidAsStringRef(); std::string Name = "_GUID_" + Uuid.lower(); std::replace(Name.begin(), Name.end(), '-', '_'); diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 1299694..24c9844 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -508,23 +508,60 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc, return BuildCXXTypeId(TypeInfoType, OpLoc, (Expr*)TyOrExpr, RParenLoc); } +/// Grabs __declspec(uuid()) off a type, or returns 0 if we cannot resolve to +/// a single GUID. +static void +getUuidAttrOfType(Sema &SemaRef, QualType QT, + llvm::SmallSetVector &UuidAttrs) { + // Optionally remove one level of pointer, reference or array indirection. + const Type *Ty = QT.getTypePtr(); + if (QT->isPointerType() || QT->isReferenceType()) + Ty = QT->getPointeeType().getTypePtr(); + else if (QT->isArrayType()) + Ty = Ty->getBaseElementTypeUnsafe(); + + const auto *RD = Ty->getAsCXXRecordDecl(); + if (!RD) + return; + + if (const auto *Uuid = RD->getMostRecentDecl()->getAttr()) { + UuidAttrs.insert(Uuid); + return; + } + + // __uuidof can grab UUIDs from template arguments. + if (const auto *CTSD = dyn_cast(RD)) { + const TemplateArgumentList &TAL = CTSD->getTemplateArgs(); + for (const TemplateArgument &TA : TAL.asArray()) { + const UuidAttr *UuidForTA = nullptr; + if (TA.getKind() == TemplateArgument::Type) + getUuidAttrOfType(SemaRef, TA.getAsType(), UuidAttrs); + else if (TA.getKind() == TemplateArgument::Declaration) + getUuidAttrOfType(SemaRef, TA.getAsDecl()->getType(), UuidAttrs); + + if (UuidForTA) + UuidAttrs.insert(UuidForTA); + } + } +} + /// \brief Build a Microsoft __uuidof expression with a type operand. ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType, SourceLocation TypeidLoc, TypeSourceInfo *Operand, SourceLocation RParenLoc) { + const UuidAttr *UA = nullptr; if (!Operand->getType()->isDependentType()) { - bool HasMultipleGUIDs = false; - if (!CXXUuidofExpr::GetUuidAttrOfType(Operand->getType(), - &HasMultipleGUIDs)) { - if (HasMultipleGUIDs) - return ExprError(Diag(TypeidLoc, diag::err_uuidof_with_multiple_guids)); - else - return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid)); - } + llvm::SmallSetVector UuidAttrs; + getUuidAttrOfType(*this, Operand->getType(), UuidAttrs); + if (UuidAttrs.empty()) + return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid)); + if (UuidAttrs.size() > 1) + return ExprError(Diag(TypeidLoc, diag::err_uuidof_with_multiple_guids)); + UA = UuidAttrs.back(); } - return new (Context) CXXUuidofExpr(TypeInfoType.withConst(), Operand, + return new (Context) CXXUuidofExpr(TypeInfoType.withConst(), Operand, UA, SourceRange(TypeidLoc, RParenLoc)); } @@ -533,18 +570,20 @@ ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType, SourceLocation TypeidLoc, Expr *E, SourceLocation RParenLoc) { + const UuidAttr *UA = nullptr; if (!E->getType()->isDependentType()) { - bool HasMultipleGUIDs = false; - if (!CXXUuidofExpr::GetUuidAttrOfType(E->getType(), &HasMultipleGUIDs) && - !E->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { - if (HasMultipleGUIDs) - return ExprError(Diag(TypeidLoc, diag::err_uuidof_with_multiple_guids)); - else + if (!E->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { + llvm::SmallSetVector UuidAttrs; + getUuidAttrOfType(*this, E->getType(), UuidAttrs); + if (UuidAttrs.empty()) return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid)); + if (UuidAttrs.size() > 1) + return ExprError(Diag(TypeidLoc, diag::err_uuidof_with_multiple_guids)); + UA = UuidAttrs.back(); } } - return new (Context) CXXUuidofExpr(TypeInfoType.withConst(), E, + return new (Context) CXXUuidofExpr(TypeInfoType.withConst(), E, UA, SourceRange(TypeidLoc, RParenLoc)); } -- 2.7.4