From: Francois Pichet Date: Mon, 20 Dec 2010 03:51:03 +0000 (+0000) Subject: Emit an error if operator __uuidof() is called on a type with no associated GUID. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=913b7bf8c40454641588611b7bbad981dc53c882;p=clang Emit an error if operator __uuidof() is called on a type with no associated GUID. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@122226 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 8dfc391ee3..32bf184f6e 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -2595,6 +2595,8 @@ def err_need_header_before_typeid : Error< "you need to include before using the 'typeid' operator">; def err_need_header_before_ms_uuidof : Error< "you need to include before using the '__uuidof' operator">; +def err_uuidof_without_guid : Error< + "cannot call operator __uuidof on a type with no GUID">; 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">; diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 79b9c45e22..d23401c666 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -372,11 +372,29 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc, return BuildCXXTypeId(TypeInfoType, OpLoc, (Expr*)TyOrExpr, RParenLoc); } +// Get the CXXRecordDecl associated with QT bypassing 1 level of pointer, +// reference or array type. +static CXXRecordDecl *GetCXXRecordOfUuidArg(QualType QT) +{ + Type* Ty = QT.getTypePtr();; + if (QT->isPointerType() || QT->isReferenceType()) + Ty = QT->getPointeeType().getTypePtr(); + else if (QT->isArrayType()) + Ty = cast(QT)->getElementType().getTypePtr(); + + return Ty->getAsCXXRecordDecl(); +} + /// \brief Build a Microsoft __uuidof expression with a type operand. ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType, SourceLocation TypeidLoc, TypeSourceInfo *Operand, SourceLocation RParenLoc) { + // Make sure Operand has an associated GUID. + CXXRecordDecl* RD = GetCXXRecordOfUuidArg(Operand->getType()); + if (!RD || !RD->getAttr()) + 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, @@ -388,6 +406,13 @@ ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType, SourceLocation TypeidLoc, Expr *E, SourceLocation RParenLoc) { + // Make sure E has an associated GUID. + // 0 is fine also. + CXXRecordDecl* RD = GetCXXRecordOfUuidArg(E->getType()); + if ((!RD || !RD->getAttr()) && + !E->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) + return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid)); + // FIXME: add __uuidof semantic analysis for expr operand. return Owned(new (Context) CXXUuidofExpr(TypeInfoType.withConst(), E, diff --git a/test/Parser/MicrosoftExtensions.c b/test/Parser/MicrosoftExtensions.c index 98c86253f7..9df8fa3a4e 100644 --- a/test/Parser/MicrosoftExtensions.c +++ b/test/Parser/MicrosoftExtensions.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple i386-mingw32 -fsyntax-only -verify -fms-extensions -Wno-unused-value -Wno-missing-declarations -x objective-c++ %s +// RUN: %clang_cc1 -triple i386-mingw32 -fsyntax-only -verify -fms-extensions -Wno-missing-declarations -x objective-c++ %s __stdcall int func0(); int __stdcall func(); typedef int (__cdecl *tptr)(); @@ -43,51 +43,9 @@ char x = FOO(a); typedef enum E { e1 }; -void uuidof_test1() -{ - __uuidof(0); // expected-error {{you need to include before using the '__uuidof' operator}} -} - -typedef struct _GUID -{ - unsigned long Data1; - unsigned short Data2; - unsigned short Data3; - unsigned char Data4[8]; -} GUID; - -struct __declspec(uuid(L"00000000-0000-0000-1234-000000000047")) uuid_attr_bad1 { };// expected-error {{'uuid' attribute requires parameter 1 to be a string}} -struct __declspec(uuid(3)) uuid_attr_bad2 { };// expected-error {{'uuid' attribute requires parameter 1 to be a string}} -struct __declspec(uuid("0000000-0000-0000-1234-0000500000047")) uuid_attr_bad3 { };// expected-error {{uuid attribute contains a malformed GUID}} -struct __declspec(uuid("0000000-0000-0000-Z234-000000000047")) uuid_attr_bad4 { };// expected-error {{uuid attribute contains a malformed GUID}} -struct __declspec(uuid("000000000000-0000-1234-000000000047")) uuid_attr_bad5 { };// expected-error {{uuid attribute contains a malformed GUID}} + -struct __declspec(uuid("00000000-0000-0000-3231-000000000046")) A { }; -struct __declspec(uuid("{00000000-0000-0000-1234-000000000047}")) B { }; -class C {}; - -void uuidof_test2() -{ - A* a = new A; - B b; - __uuidof(A); - __uuidof(*a); - __uuidof(B); - __uuidof(&b); - _uuidof(0); - - // FIXME, this must not compile - _uuidof(1); - // FIXME, this must not compile - _uuidof(C); - - C c; - // FIXME, this must not compile - _uuidof(c); - - &_uuidof(0); -} /* Microsoft attribute tests */ [repeatable][source_annotation_attribute( Parameter|ReturnValue )] diff --git a/test/Parser/MicrosoftExtensions.cpp b/test/Parser/MicrosoftExtensions.cpp index e55e74cb83..ef4a3f6d78 100644 --- a/test/Parser/MicrosoftExtensions.cpp +++ b/test/Parser/MicrosoftExtensions.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -fsyntax-only -Wmicrosoft -verify -fms-extensions +// RUN: %clang_cc1 %s -fsyntax-only -Wno-unused-value -Wmicrosoft -verify -fms-extensions /* Microsoft attribute tests */ [repeatable][source_annotation_attribute( Parameter|ReturnValue )] @@ -23,3 +23,49 @@ extern "C" { } +void uuidof_test1() +{ + __uuidof(0); // expected-error {{you need to include before using the '__uuidof' operator}} +} + +typedef struct _GUID +{ + unsigned long Data1; + unsigned short Data2; + unsigned short Data3; + unsigned char Data4[8]; +} GUID; + +struct __declspec(uuid(L"00000000-0000-0000-1234-000000000047")) uuid_attr_bad1 { };// expected-error {{'uuid' attribute requires parameter 1 to be a string}} +struct __declspec(uuid(3)) uuid_attr_bad2 { };// expected-error {{'uuid' attribute requires parameter 1 to be a string}} +struct __declspec(uuid("0000000-0000-0000-1234-0000500000047")) uuid_attr_bad3 { };// expected-error {{uuid attribute contains a malformed GUID}} +struct __declspec(uuid("0000000-0000-0000-Z234-000000000047")) uuid_attr_bad4 { };// expected-error {{uuid attribute contains a malformed GUID}} +struct __declspec(uuid("000000000000-0000-1234-000000000047")) uuid_attr_bad5 { };// expected-error {{uuid attribute contains a malformed GUID}} + + + +struct __declspec(uuid("000000A0-0000-0000-C000-000000000046")) +struct_with_uuid { }; +struct struct_without_uuid { }; + + +int uuid_sema_test() +{ + struct_with_uuid var_with_uuid[1]; + struct_without_uuid var_without_uuid[1]; + + __uuidof(struct_with_uuid); + __uuidof(struct_without_uuid); // expected-error {{cannot call operator __uuidof on a type with no GUID}} + __uuidof(struct_with_uuid*); + __uuidof(struct_without_uuid*); // expected-error {{cannot call operator __uuidof on a type with no GUID}} + + __uuidof(var_with_uuid); + __uuidof(var_without_uuid);// expected-error {{cannot call operator __uuidof on a type with no GUID}} + __uuidof(var_with_uuid[1]); + __uuidof(var_without_uuid[1]);// expected-error {{cannot call operator __uuidof on a type with no GUID}} + __uuidof(&var_with_uuid[1]); + __uuidof(&var_without_uuid[1]);// expected-error {{cannot call operator __uuidof on a type with no GUID}} + + __uuidof(0); + __uuidof(1);// expected-error {{cannot call operator __uuidof on a type with no GUID}} +}