diff options
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 42 | ||||
-rw-r--r-- | test/Parser/MicrosoftExtensions.c | 10 |
3 files changed, 51 insertions, 3 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index cfa2ab6d21..b616cd9a3c 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -929,6 +929,8 @@ def err_attribute_argument_out_of_bounds : Error< "'%0' attribute parameter %1 is out of bounds">; def err_attribute_requires_objc_interface : Error< "attribute may only be applied to an Objective-C interface">; +def err_attribute_uuid_malformed_guid : Error< + "uuid attribute contains a malformed GUID">; def warn_nonnull_pointers_only : Warning< "nonnull attribute only applies to pointer arguments">; def err_attribute_invalid_implicit_this_argument : Error< diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index b0e022fd33..e77a660ada 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -2533,12 +2533,50 @@ static void HandleUuidAttr(Decl *d, const AttributeList &Attr, Sema &S) { } Expr *Arg = Attr.getArg(0); StringLiteral *Str = dyn_cast<StringLiteral>(Arg); + if (Str == 0 || Str->isWide()) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) + << "uuid" << 1; + return; + } + + llvm::StringRef StrRef = Str->getString(); + + bool IsCurly = StrRef.size() > 1 && StrRef.front() == '{' && + StrRef.back() == '}'; + + // Validate GUID length. + if (IsCurly && StrRef.size() != 38) { + S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid); + return; + } + if (!IsCurly && StrRef.size() != 36) { + S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid); + return; + } + + // GUID format is "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" or + // "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}" + llvm::StringRef::iterator I = StrRef.begin();
+ if (IsCurly) // Skip the optional '{'
+ ++I;
+
+ for (int i = 0; i < 36; ++i) {
+ if (i == 8 || i == 13 || i == 18 || i == 23) { + if (*I != '-') { + S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid); + return; + } + } else if (!isxdigit(*I)) { + S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid); + return; + } + I++; + } d->addAttr(::new (S.Context) UuidAttr(Attr.getLoc(), S.Context, Str->getString())); - } else { + } else S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "uuid"; - } } //===----------------------------------------------------------------------===// diff --git a/test/Parser/MicrosoftExtensions.c b/test/Parser/MicrosoftExtensions.c index 6c14742278..98c86253f7 100644 --- a/test/Parser/MicrosoftExtensions.c +++ b/test/Parser/MicrosoftExtensions.c @@ -55,8 +55,16 @@ typedef struct _GUID 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 { }; +struct __declspec(uuid("{00000000-0000-0000-1234-000000000047}")) B { }; class C {}; void uuidof_test2() |