Index: cfe/trunk/include/clang/Basic/Attr.td =================================================================== --- cfe/trunk/include/clang/Basic/Attr.td +++ cfe/trunk/include/clang/Basic/Attr.td @@ -1618,7 +1618,9 @@ def Uuid : InheritableAttr { let Spellings = [Declspec<"uuid">, Microsoft<"uuid">]; let Args = [StringArgument<"Guid">]; -// let Subjects = SubjectList<[CXXRecord]>; + let Subjects = SubjectList<[Record, Enum], WarnDiag, "ExpectedEnumOrClass">; + // FIXME: Allow expressing logical AND for LangOpts. Our condition should be: + // CPlusPlus && (MicrosoftExt || Borland) let LangOpts = [MicrosoftExt, Borland]; let Documentation = [Undocumented]; } Index: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td @@ -2650,7 +2650,8 @@ "|variables, enums, fields and typedefs" "|functions, methods, enums, and classes" "|structs, classes, variables, functions, and inline namespaces" - "|variables, functions, methods, types, enumerations, enumerators, labels, and non-static data members}1">, + "|variables, functions, methods, types, enumerations, enumerators, labels, and non-static data members" + "|classes and enumerations}1">, InGroup; def err_attribute_wrong_decl_type : Error; def warn_type_attribute_wrong_type : Warning< Index: cfe/trunk/include/clang/Sema/AttributeList.h =================================================================== --- cfe/trunk/include/clang/Sema/AttributeList.h +++ cfe/trunk/include/clang/Sema/AttributeList.h @@ -925,7 +925,8 @@ ExpectedVariableEnumFieldOrTypedef, ExpectedFunctionMethodEnumOrClass, ExpectedStructClassVariableFunctionOrInlineNamespace, - ExpectedForMaybeUnused + ExpectedForMaybeUnused, + ExpectedEnumOrClass, }; } // end namespace clang Index: cfe/trunk/lib/Sema/SemaDeclAttr.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaDeclAttr.cpp +++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp @@ -4666,12 +4666,6 @@ return; } - if (!isa(D)) { - S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << ExpectedClass; - return; - } - StringRef StrRef; SourceLocation LiteralLoc; if (!S.checkStringLiteralArgumentAttr(Attr, 0, StrRef, &LiteralLoc)) Index: cfe/trunk/lib/Sema/SemaExprCXX.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaExprCXX.cpp +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp @@ -520,17 +520,17 @@ else if (QT->isArrayType()) Ty = Ty->getBaseElementTypeUnsafe(); - const auto *RD = Ty->getAsCXXRecordDecl(); - if (!RD) + const auto *TD = Ty->getAsTagDecl(); + if (!TD) return; - if (const auto *Uuid = RD->getMostRecentDecl()->getAttr()) { + if (const auto *Uuid = TD->getMostRecentDecl()->getAttr()) { UuidAttrs.insert(Uuid); return; } // __uuidof can grab UUIDs from template arguments. - if (const auto *CTSD = dyn_cast(RD)) { + if (const auto *CTSD = dyn_cast(TD)) { const TemplateArgumentList &TAL = CTSD->getTemplateArgs(); for (const TemplateArgument &TA : TAL.asArray()) { const UuidAttr *UuidForTA = nullptr; Index: cfe/trunk/test/Parser/MicrosoftExtensions.cpp =================================================================== --- cfe/trunk/test/Parser/MicrosoftExtensions.cpp +++ cfe/trunk/test/Parser/MicrosoftExtensions.cpp @@ -65,6 +65,12 @@ struct struct_with_uuid2 {} ; +enum __declspec(uuid("000000A0-0000-0000-C000-000000000046")) +enum_with_uuid { }; +enum enum_without_uuid { }; + +int __declspec(uuid("000000A0-0000-0000-C000-000000000046")) inappropriate_uuid; // expected-warning {{'uuid' attribute only applies to classes and enumerations}} + int uuid_sema_test() { struct_with_uuid var_with_uuid[1]; @@ -81,6 +87,15 @@ __uuidof(const struct_with_uuid[1][1]); __uuidof(const struct_with_uuid*[1][1]); // expected-error {{cannot call operator __uuidof on a type with no GUID}} + __uuidof(enum_with_uuid); + __uuidof(enum_without_uuid); // expected-error {{cannot call operator __uuidof on a type with no GUID}} + __uuidof(enum_with_uuid*); + __uuidof(enum_without_uuid*); // expected-error {{cannot call operator __uuidof on a type with no GUID}} + __uuidof(enum_with_uuid[1]); + __uuidof(enum_with_uuid*[1]); // expected-error {{cannot call operator __uuidof on a type with no GUID}} + __uuidof(const enum_with_uuid[1][1]); + __uuidof(const enum_with_uuid*[1][1]); // 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]);