Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -2387,8 +2387,9 @@ def err_attribute_requires_opencl_version : Error< "%0 attribute requires OpenCL version %1%select{| or above}2">; def warn_unsupported_target_attribute - : Warning<"Ignoring unsupported '%0' in the target attribute string">, - InGroup; + : Warning<"ignoring %select{unsupported|duplicate}0" + "%select{| architecture}1 '%2' in the target attribute string">, + InGroup; def err_attribute_unsupported : Error<"%0 attribute is not supported for this target">; // The err_*_attribute_argument_not_int are separate because they're used by Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -3271,7 +3271,7 @@ unsigned ArgNum, StringRef &Str, SourceLocation *ArgLocation = nullptr); bool checkSectionName(SourceLocation LiteralLoc, StringRef Str); - void checkTargetAttr(SourceLocation LiteralLoc, StringRef Str); + bool checkTargetAttr(SourceLocation LiteralLoc, StringRef Str); bool checkMSInheritanceAttrOnDefinition( CXXRecordDecl *RD, SourceRange Range, bool BestCase, MSInheritanceAttr::Spelling SemanticSpelling); Index: lib/Sema/SemaDeclAttr.cpp =================================================================== --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -2993,22 +2993,43 @@ D->addAttr(NewAttr); } -// Check for things we'd like to warn about, no errors or validation for now. -// TODO: Validation should use a backend target library that specifies -// the allowable subtarget features and cpus. We could use something like a -// TargetCodeGenInfo hook here to do validation. -void Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) { +// Check for things we'd like to warn about. Multiversioning issues are +// handled later in the process, once we know how many exist. +bool Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) { + enum FirstParam { Unsupported, Duplicate }; + enum SecondParam { None, Architecture }; for (auto Str : {"tune=", "fpmath="}) if (AttrStr.find(Str) != StringRef::npos) - Diag(LiteralLoc, diag::warn_unsupported_target_attribute) << Str; + return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) + << Unsupported << None << Str; + + TargetAttr::ParsedTargetAttr ParsedAttrs = TargetAttr::parse(AttrStr); + + if (!ParsedAttrs.Architecture.empty() && + !Context.getTargetInfo().isValidCPUName(ParsedAttrs.Architecture)) + return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) + << Unsupported << Architecture << ParsedAttrs.Architecture; + + if (ParsedAttrs.DuplicateArchitecture) + return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) + << Duplicate << None << "arch="; + + for (const auto &Feature : ParsedAttrs.Features) { + auto CurFeature = StringRef(Feature).drop_front(); // remove + or -. + if (!Context.getTargetInfo().isValidFeatureName(CurFeature)) + return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) + << Unsupported << None << CurFeature; + } + + return true; } static void handleTargetAttr(Sema &S, Decl *D, const AttributeList &Attr) { StringRef Str; SourceLocation LiteralLoc; - if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str, &LiteralLoc)) + if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str, &LiteralLoc) || + !S.checkTargetAttr(LiteralLoc, Str)) return; - S.checkTargetAttr(LiteralLoc, Str); unsigned Index = Attr.getAttributeSpellingListIndex(); TargetAttr *NewAttr = ::new (S.Context) TargetAttr(Attr.getRange(), S.Context, Str, Index); Index: test/Sema/attr-target.c =================================================================== --- test/Sema/attr-target.c +++ test/Sema/attr-target.c @@ -2,7 +2,13 @@ int __attribute__((target("avx,sse4.2,arch=ivybridge"))) foo() { return 4; } int __attribute__((target())) bar() { return 4; } //expected-error {{'target' attribute takes one argument}} -int __attribute__((target("tune=sandybridge"))) baz() { return 4; } //expected-warning {{Ignoring unsupported 'tune=' in the target attribute string}} -int __attribute__((target("fpmath=387"))) walrus() { return 4; } //expected-warning {{Ignoring unsupported 'fpmath=' in the target attribute string}} +int __attribute__((target("tune=sandybridge"))) baz() { return 4; } //expected-warning {{ignoring unsupported 'tune=' in the target attribute string}} +int __attribute__((target("fpmath=387"))) walrus() { return 4; } //expected-warning {{ignoring unsupported 'fpmath=' in the target attribute string}} +int __attribute__((target("avx,sse4.2,arch=hiss"))) meow() { return 4; }//expected-warning {{ignoring unsupported architecture 'hiss' in the target attribute string}} +int __attribute__((target("woof"))) bark() { return 4; }//expected-warning {{ignoring unsupported 'woof' in the target attribute string}} +int __attribute__((target("arch="))) turtle() { return 4; } // no warning, same as saying 'nothing'. +int __attribute__((target("arch=hiss,arch=woof"))) pine_tree() { return 4; } //expected-warning {{ignoring unsupported architecture 'hiss' in the target attribute string}} +int __attribute__((target("arch=ivybridge,arch=haswell"))) oak_tree() { return 4; } //expected-warning {{ignoring duplicate 'arch=' in the target attribute string}} +