Author: majnemer Date: Sat Sep 7 01:59:46 2013 New Revision: 190240 URL: http://llvm.org/viewvc/llvm-project?rev=190240&view=rev Log: AST: __uuidof should leak through templated types
Summary: __uuidof on templated types should exmaine if any of its template parameters have a uuid declspec. If exactly one does, then take it. Otherwise, issue an appropriate error. Reviewers: rsmith, thakis, rnk CC: cfe-commits Differential Revision: http://llvm-reviews.chandlerc.com/D1419 Modified: cfe/trunk/include/clang/AST/ExprCXX.h cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/lib/AST/ExprCXX.cpp cfe/trunk/lib/Sema/SemaExprCXX.cpp cfe/trunk/test/Parser/MicrosoftExtensions.cpp Modified: cfe/trunk/include/clang/AST/ExprCXX.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=190240&r1=190239&r2=190240&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/ExprCXX.h (original) +++ cfe/trunk/include/clang/AST/ExprCXX.h Sat Sep 7 01:59:46 2013 @@ -735,8 +735,10 @@ public: return T->getStmtClass() == CXXUuidofExprClass; } - /// Grabs __declspec(uuid()) off a type, or returns 0 if there is none. - static UuidAttr *GetUuidAttrOfType(QualType QT); + /// Grabs __declspec(uuid()) off a type, or returns 0 if we cannot resolve to + /// a single GUID. + static UuidAttr *GetUuidAttrOfType(QualType QT, + bool *HasMultipleGUIDsPtr = 0); // Iterators child_range children() { Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=190240&r1=190239&r2=190240&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sat Sep 7 01:59:46 2013 @@ -4858,6 +4858,8 @@ def err_need_header_before_ms_uuidof : E "you need to include <guiddef.h> before using the '__uuidof' operator">; def err_uuidof_without_guid : Error< "cannot call operator __uuidof on a type with no GUID">; +def err_uuidof_with_multiple_guids : Error< + "cannot call operator __uuidof on a type with multiple GUIDs">; def err_incomplete_typeid : Error<"'typeid' of incomplete type %0">; def err_static_illegal_in_new : Error< "the 'static' modifier for the array size is not legal in new expressions">; Modified: cfe/trunk/lib/AST/ExprCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=190240&r1=190239&r2=190240&view=diff ============================================================================== --- cfe/trunk/lib/AST/ExprCXX.cpp (original) +++ cfe/trunk/lib/AST/ExprCXX.cpp Sat Sep 7 01:59:46 2013 @@ -53,7 +53,8 @@ QualType CXXUuidofExpr::getTypeOperand() } // static -UuidAttr *CXXUuidofExpr::GetUuidAttrOfType(QualType QT) { +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()) @@ -63,11 +64,51 @@ UuidAttr *CXXUuidofExpr::GetUuidAttrOfTy // Loop all record redeclaration looking for an uuid attribute. CXXRecordDecl *RD = Ty->getAsCXXRecordDecl(); - for (CXXRecordDecl::redecl_iterator I = RD->redecls_begin(), - E = RD->redecls_end(); I != E; ++I) { - if (UuidAttr *Uuid = I->getAttr<UuidAttr>()) - return Uuid; - } + if (!RD) + return 0; + + if (ClassTemplateSpecializationDecl *CTSD = + dyn_cast<ClassTemplateSpecializationDecl>(RD)) { + const TemplateArgumentList &TAL = CTSD->getTemplateArgs(); + UuidAttr *UuidForRD = 0; + + for (unsigned I = 0, N = TAL.size(); I != N; ++I) { + const TemplateArgument &TA = TAL[I]; + bool SeenMultipleGUIDs = false; + + UuidAttr *UuidForTA = 0; + 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 seed for this RecordDecl. + // - This is the same UUID than previously seed 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 0; + } + } + + return UuidForRD; + } else + for (CXXRecordDecl::redecl_iterator I = RD->redecls_begin(), + E = RD->redecls_end(); + I != E; ++I) + if (UuidAttr *Uuid = I->getAttr<UuidAttr>()) + return Uuid; return 0; } Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=190240&r1=190239&r2=190240&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original) +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Sat Sep 7 01:59:46 2013 @@ -462,11 +462,16 @@ ExprResult Sema::BuildCXXUuidof(QualType TypeSourceInfo *Operand, SourceLocation RParenLoc) { if (!Operand->getType()->isDependentType()) { - if (!CXXUuidofExpr::GetUuidAttrOfType(Operand->getType())) - return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid)); + 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)); + } } - // FIXME: add __uuidof semantic analysis for type operand. return Owned(new (Context) CXXUuidofExpr(TypeInfoType.withConst(), Operand, SourceRange(TypeidLoc, RParenLoc))); @@ -478,11 +483,16 @@ ExprResult Sema::BuildCXXUuidof(QualType Expr *E, SourceLocation RParenLoc) { if (!E->getType()->isDependentType()) { - if (!CXXUuidofExpr::GetUuidAttrOfType(E->getType()) && - !E->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) - return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid)); + 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 + return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid)); + } } - // FIXME: add __uuidof semantic analysis for type operand. + return Owned(new (Context) CXXUuidofExpr(TypeInfoType.withConst(), E, SourceRange(TypeidLoc, RParenLoc))); Modified: cfe/trunk/test/Parser/MicrosoftExtensions.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/MicrosoftExtensions.cpp?rev=190240&r1=190239&r2=190240&view=diff ============================================================================== --- cfe/trunk/test/Parser/MicrosoftExtensions.cpp (original) +++ cfe/trunk/test/Parser/MicrosoftExtensions.cpp Sat Sep 7 01:59:46 2013 @@ -116,6 +116,25 @@ COM_CLASS_TEMPLATE_REF<int, __uuidof(str COM_CLASS_TEMPLATE<int, __uuidof(struct_with_uuid)> bad_template_arg; // expected-error {{non-type template argument of type 'const _GUID' is not a constant expression}} +namespace PR16911 { +struct __declspec(uuid("{12345678-1234-1234-1234-1234567890aB}")) uuid; +struct __declspec(uuid("{12345678-1234-1234-1234-1234567890aB}")) uuid2; + +template <typename T, typename T2> +struct thing { +}; + +struct empty {}; +struct inher : public thing<empty, uuid2> {}; + +struct __declspec(uuid("{12345678-1234-1234-1234-1234567890aB}")) uuid; +const struct _GUID *w = &__uuidof(inher); // expected-error{{cannot call operator __uuidof on a type with no GUID}} +const struct _GUID *x = &__uuidof(thing<uuid, inher>); +const struct _GUID *y = &__uuidof(thing<uuid2, uuid>); // expected-error{{cannot call operator __uuidof on a type with multiple GUIDs}} +thing<uuid2, uuid> thing_obj = thing<uuid2, uuid>(); +const struct _GUID *z = &__uuidof(thing_obj); // expected-error{{cannot call operator __uuidof on a type with multiple GUIDs}} +} + class CtorCall { public: CtorCall& operator=(const CtorCall& that); _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
