diff options
-rw-r--r-- | clang/include/clang/Basic/Attr.td | 8 | ||||
-rw-r--r-- | clang/include/clang/Basic/Attributes.h | 4 | ||||
-rw-r--r-- | clang/include/clang/Sema/AttributeList.h | 4 | ||||
-rw-r--r-- | clang/lib/Basic/Attributes.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Lex/PPMacroExpansion.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/AttributeList.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 2 | ||||
-rw-r--r-- | clang/test/Parser/MicrosoftExtensions.cpp | 2 | ||||
-rw-r--r-- | clang/test/SemaCXX/ms-novtable.cpp | 2 | ||||
-rw-r--r-- | clang/test/SemaCXX/ms-unsupported.cpp | 5 | ||||
-rw-r--r-- | clang/utils/TableGen/ClangAttrEmitter.cpp | 39 |
13 files changed, 65 insertions, 22 deletions
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 11b3263d705..753e42c950a 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -241,14 +241,18 @@ def COnly : LangOpt<"CPlusPlus", 1>; class TargetArch<list<string> arches> { list<string> Arches = arches; list<string> OSes; + list<string> CXXABIs; } def TargetARM : TargetArch<["arm", "thumb"]>; +def TargetMips : TargetArch<["mips", "mipsel"]>; def TargetMSP430 : TargetArch<["msp430"]>; def TargetX86 : TargetArch<["x86"]>; def TargetWindows : TargetArch<["x86", "x86_64", "arm", "thumb"]> { let OSes = ["Win32"]; } -def TargetMips : TargetArch<["mips", "mipsel"]>; +def TargetMicrosoftCXXABI : TargetArch<["x86", "x86_64", "arm", "thumb"]> { + let CXXABIs = ["Microsoft"]; +} class Attr { // The various ways in which an attribute can be spelled in source @@ -1820,7 +1824,7 @@ def TypeTagForDatatype : InheritableAttr { // Microsoft-related attributes -def MSNoVTable : InheritableAttr { +def MSNoVTable : InheritableAttr, TargetSpecificAttr<TargetMicrosoftCXXABI> { let Spellings = [Declspec<"novtable">]; let Subjects = SubjectList<[CXXRecord]>; let Documentation = [MSNoVTableDocs]; diff --git a/clang/include/clang/Basic/Attributes.h b/clang/include/clang/Basic/Attributes.h index a64dd5666b7..a2b86841cdd 100644 --- a/clang/include/clang/Basic/Attributes.h +++ b/clang/include/clang/Basic/Attributes.h @@ -11,7 +11,7 @@ #define LLVM_CLANG_BASIC_ATTRIBUTES_H #include "clang/Basic/LangOptions.h" -#include "llvm/ADT/Triple.h" +#include "clang/Basic/TargetInfo.h" namespace clang { @@ -31,7 +31,7 @@ enum class AttrSyntax { /// \brief Return the version number associated with the attribute if we /// recognize and implement the attribute specified by the given information. int hasAttribute(AttrSyntax Syntax, const IdentifierInfo *Scope, - const IdentifierInfo *Attr, const llvm::Triple &T, + const IdentifierInfo *Attr, const TargetInfo &Target, const LangOptions &LangOpts); } // end namespace clang diff --git a/clang/include/clang/Sema/AttributeList.h b/clang/include/clang/Sema/AttributeList.h index 2fedc79401f..ca456b2f9bb 100644 --- a/clang/include/clang/Sema/AttributeList.h +++ b/clang/include/clang/Sema/AttributeList.h @@ -16,11 +16,11 @@ #define LLVM_CLANG_SEMA_ATTRIBUTELIST_H #include "clang/Basic/SourceLocation.h" +#include "clang/Basic/TargetInfo.h" #include "clang/Basic/VersionTuple.h" #include "clang/Sema/Ownership.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/Triple.h" #include "llvm/Support/Allocator.h" #include <cassert> @@ -464,7 +464,7 @@ public: bool hasVariadicArg() const; bool diagnoseAppertainsTo(class Sema &S, const Decl *D) const; bool diagnoseLangOpts(class Sema &S) const; - bool existsInTarget(const llvm::Triple &T) const; + bool existsInTarget(const TargetInfo &Target) const; bool isKnownToGCC() const; /// \brief If the parsed attribute has a semantic equivalent, and it would diff --git a/clang/lib/Basic/Attributes.cpp b/clang/lib/Basic/Attributes.cpp index da9ac793f16..c215366fc39 100644 --- a/clang/lib/Basic/Attributes.cpp +++ b/clang/lib/Basic/Attributes.cpp @@ -4,8 +4,8 @@ using namespace clang; int clang::hasAttribute(AttrSyntax Syntax, const IdentifierInfo *Scope, - const IdentifierInfo *Attr, const llvm::Triple &T, - const LangOptions &LangOpts) { + const IdentifierInfo *Attr, const TargetInfo &Target, + const LangOptions &LangOpts) { StringRef Name = Attr->getName(); // Normalize the attribute name, __foo__ becomes foo. if (Name.size() >= 4 && Name.startswith("__") && Name.endswith("__")) diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp index 1324ca93451..42b1d048c40 100644 --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -1633,13 +1633,13 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { Value = FeatureII->getBuiltinID() != 0; } else if (II == Ident__has_attribute) Value = hasAttribute(AttrSyntax::GNU, nullptr, FeatureII, - getTargetInfo().getTriple(), getLangOpts()); + getTargetInfo(), getLangOpts()); else if (II == Ident__has_cpp_attribute) Value = hasAttribute(AttrSyntax::CXX, ScopeII, FeatureII, - getTargetInfo().getTriple(), getLangOpts()); + getTargetInfo(), getLangOpts()); else if (II == Ident__has_declspec) Value = hasAttribute(AttrSyntax::Declspec, nullptr, FeatureII, - getTargetInfo().getTriple(), getLangOpts()); + getTargetInfo(), getLangOpts()); else if (II == Ident__has_extension) Value = HasExtension(*this, FeatureII); else { diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index f46af889e25..acfe0ca0e82 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -387,7 +387,7 @@ bool Parser::ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName, // If the attribute isn't known, we will not attempt to parse any // arguments. if (!hasAttribute(AttrSyntax::Declspec, nullptr, AttrName, - getTargetInfo().getTriple(), getLangOpts())) { + getTargetInfo(), getLangOpts())) { // Eat the left paren, then skip to the ending right paren. ConsumeParen(); SkipUntil(tok::r_paren); diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index e347d4e27e2..0fb1de94e8e 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -3612,7 +3612,7 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName, // If the attribute isn't known, we will not attempt to parse any // arguments. if (!hasAttribute(AttrSyntax::CXX, ScopeName, AttrName, - getTargetInfo().getTriple(), getLangOpts())) { + getTargetInfo(), getLangOpts())) { // Eat the left paren, then skip to the ending right paren. ConsumeParen(); SkipUntil(tok::r_paren); diff --git a/clang/lib/Sema/AttributeList.cpp b/clang/lib/Sema/AttributeList.cpp index 34af6cf63c8..1ea40606f44 100644 --- a/clang/lib/Sema/AttributeList.cpp +++ b/clang/lib/Sema/AttributeList.cpp @@ -17,6 +17,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/TargetInfo.h" #include "clang/Sema/SemaInternal.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringSwitch.h" @@ -155,7 +156,7 @@ struct ParsedAttrInfo { bool (*DiagAppertainsToDecl)(Sema &S, const AttributeList &Attr, const Decl *); bool (*DiagLangOpts)(Sema &S, const AttributeList &Attr); - bool (*ExistsInTarget)(const llvm::Triple &T); + bool (*ExistsInTarget)(const TargetInfo &Target); unsigned (*SpellingIndexToSemanticSpelling)(const AttributeList &Attr); }; @@ -195,8 +196,8 @@ bool AttributeList::isTypeAttr() const { return getInfo(*this).IsType; } -bool AttributeList::existsInTarget(const llvm::Triple &T) const { - return getInfo(*this).ExistsInTarget(T); +bool AttributeList::existsInTarget(const TargetInfo &Target) const { + return getInfo(*this).ExistsInTarget(Target); } bool AttributeList::isKnownToGCC() const { diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 9ec3356d048..3395381b6a3 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -4583,7 +4583,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, // which do not apply to the current target architecture are treated as // though they were unknown attributes. if (Attr.getKind() == AttributeList::UnknownAttribute || - !Attr.existsInTarget(S.Context.getTargetInfo().getTriple())) { + !Attr.existsInTarget(S.Context.getTargetInfo())) { S.Diag(Attr.getLoc(), Attr.isDeclspecAttribute() ? diag::warn_unhandled_ms_attribute_ignored : diag::warn_unknown_attribute_ignored) diff --git a/clang/test/Parser/MicrosoftExtensions.cpp b/clang/test/Parser/MicrosoftExtensions.cpp index e674d0101e9..efb9490697e 100644 --- a/clang/test/Parser/MicrosoftExtensions.cpp +++ b/clang/test/Parser/MicrosoftExtensions.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -triple i386-mingw32 -std=c++14 -fsyntax-only -Wno-unused-getter-return-value -Wno-unused-value -Wmicrosoft -verify -fms-extensions -fms-compatibility -fdelayed-template-parsing +// RUN: %clang_cc1 %s -triple i386-pc-win32 -std=c++14 -fsyntax-only -Wno-unused-getter-return-value -Wno-unused-value -Wmicrosoft -verify -fms-extensions -fms-compatibility -fdelayed-template-parsing /* Microsoft attribute tests */ [repeatable][source_annotation_attribute( Parameter|ReturnValue )] diff --git a/clang/test/SemaCXX/ms-novtable.cpp b/clang/test/SemaCXX/ms-novtable.cpp index 2d55c48df3c..31975b3b4a8 100644 --- a/clang/test/SemaCXX/ms-novtable.cpp +++ b/clang/test/SemaCXX/ms-novtable.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -fsyntax-only -verify -fms-extensions -Wno-microsoft -std=c++11 +// RUN: %clang_cc1 -triple i386-pc-win32 %s -fsyntax-only -verify -fms-extensions -Wno-microsoft -std=c++11 struct __declspec(novtable) S {}; enum __declspec(novtable) E {}; // expected-warning{{'novtable' attribute only applies to classes}} diff --git a/clang/test/SemaCXX/ms-unsupported.cpp b/clang/test/SemaCXX/ms-unsupported.cpp new file mode 100644 index 00000000000..559d703f367 --- /dev/null +++ b/clang/test/SemaCXX/ms-unsupported.cpp @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -triple x86_64-pc-windows-gnu %s -fsyntax-only -verify -fms-extensions -Wno-microsoft -std=c++11 + +// "novtable" is ignored except with the Microsoft C++ ABI. +// MinGW uses the Itanium C++ ABI so check that it is ignored there. +struct __declspec(novtable) S {}; // expected-warning{{__declspec attribute 'novtable' is not supported}} diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp index 5dc33a000a4..c96777d1e89 100644 --- a/clang/utils/TableGen/ClangAttrEmitter.cpp +++ b/clang/utils/TableGen/ClangAttrEmitter.cpp @@ -1885,7 +1885,8 @@ static void GenerateHasAttrSpellingStringSwitch( } } - // It is assumed that there will be an llvm::Triple object named T within + // It is assumed that there will be an llvm::Triple object + // named "T" and a TargetInfo object named "Target" within // scope that can be used to determine whether the attribute exists in // a given target. std::string Test; @@ -1902,6 +1903,7 @@ static void GenerateHasAttrSpellingStringSwitch( } Test += ")"; + // If the attribute is specific to particular OSes, check those. std::vector<std::string> OSes; if (!R->isValueUnset("OSes")) { Test += " && ("; @@ -1916,6 +1918,21 @@ static void GenerateHasAttrSpellingStringSwitch( Test += ")"; } + // If one or more CXX ABIs are specified, check those as well. + if (!R->isValueUnset("CXXABIs")) { + Test += " && ("; + std::vector<std::string> CXXABIs = + R->getValueAsListOfStrings("CXXABIs"); + for (auto AI = CXXABIs.begin(), AE = CXXABIs.end(); AI != AE; ++AI) { + std::string Part = *AI; + + Test += "Target.getCXXABI().getKind() == TargetCXXABI::" + Part; + if (AI + 1 != AE) + Test += " || "; + } + Test += ")"; + } + // If this is the C++11 variety, also add in the LangOpts test. if (Variety == "CXX11") Test += " && LangOpts.CPlusPlus11"; @@ -1962,6 +1979,7 @@ void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) { } } + OS << "const llvm::Triple &T = Target.getTriple();\n"; OS << "switch (Syntax) {\n"; OS << "case AttrSyntax::GNU:\n"; OS << " return llvm::StringSwitch<int>(Name)\n"; @@ -2464,7 +2482,7 @@ static std::string GenerateLangOptRequirements(const Record &R, } static void GenerateDefaultTargetRequirements(raw_ostream &OS) { - OS << "static bool defaultTargetRequirements(const llvm::Triple &) {\n"; + OS << "static bool defaultTargetRequirements(const TargetInfo &) {\n"; OS << " return true;\n"; OS << "}\n\n"; } @@ -2533,6 +2551,20 @@ static std::string GenerateTargetRequirements(const Record &Attr, Test += ")"; } + // Test for the C++ ABI, if specified. + if (!R->isValueUnset("CXXABIs")) { + Test += " && ("; + std::vector<std::string> CXXABIs = R->getValueAsListOfStrings("CXXABIs"); + for (auto I = CXXABIs.begin(), E = CXXABIs.end(); I != E; ++I) { + std::string Part = *I; + Test += "Target.getCXXABI().getKind() == TargetCXXABI::" + Part; + if (I + 1 != E) + Test += " || "; + FnName += Part; + } + Test += ")"; + } + // If this code has already been generated, simply return the previous // instance of it. static std::set<std::string> CustomTargetSet; @@ -2540,7 +2572,8 @@ static std::string GenerateTargetRequirements(const Record &Attr, if (I != CustomTargetSet.end()) return *I; - OS << "static bool " << FnName << "(const llvm::Triple &T) {\n"; + OS << "static bool " << FnName << "(const TargetInfo &Target) {\n"; + OS << " const llvm::Triple &T = Target.getTriple();\n"; OS << " llvm::Triple::ArchType Arch = T.getArch();\n"; if (UsesOS) OS << " llvm::Triple::OSType OS = T.getOS();\n"; |