diff options
author | David Majnemer <david.majnemer@gmail.com> | 2016-03-27 04:46:07 +0000 |
---|---|---|
committer | David Majnemer <david.majnemer@gmail.com> | 2016-03-27 04:46:07 +0000 |
commit | 1dbc7a7a5a4836f84d7304762ba93da34a339c52 (patch) | |
tree | 788cff8495e6c05b6510c4ff5d487e7191284006 /clang/lib/Sema/SemaExprCXX.cpp | |
parent | ff379b69b2f82c9ca9b955b0458bb1aba85b9b85 (diff) | |
download | bcm5719-llvm-1dbc7a7a5a4836f84d7304762ba93da34a339c52.tar.gz bcm5719-llvm-1dbc7a7a5a4836f84d7304762ba93da34a339c52.zip |
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
Diffstat (limited to 'clang/lib/Sema/SemaExprCXX.cpp')
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 71 |
1 files changed, 55 insertions, 16 deletions
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 129969469ab..24c9844519e 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<const UuidAttr *, 1> &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<UuidAttr>()) { + UuidAttrs.insert(Uuid); + return; + } + + // __uuidof can grab UUIDs from template arguments. + if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(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<const UuidAttr *, 1> 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<const UuidAttr *, 1> 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)); } |