Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit 3056e7c

Browse files
committed
Reapplying r204952 a second time.
Clean up the __has_attribute implementation without modifying its behavior. Replaces the tablegen-driven AttrSpellings.inc, which lived in the lexing layer with AttrHasAttributeImpl.inc, which lives in the basic layer. Updates the preprocessor to call through to this new functionality which can take additional information into account (such as scopes and syntaxes). Expose the ability for parts of the compiler to ask whether an attribute is supported for a given spelling (including scope), syntax, triple and language options. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@205181 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 1fe9ec4 commit 3056e7c

13 files changed

+155
-55
lines changed

include/clang/Basic/Attributes.h

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//===--- Attributes.h - Attributes header -----------------------*- C++ -*-===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is distributed under the University of Illinois Open Source
6+
// License. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#ifndef LLVM_CLANG_BASIC_ATTRIBUTES_H
11+
#define LLVM_CLANG_BASIC_ATTRIBUTES_H
12+
13+
#include "llvm/ADT/Triple.h"
14+
#include "clang/Basic/LangOptions.h"
15+
16+
namespace clang {
17+
18+
class IdentifierInfo;
19+
20+
enum class AttrSyntax {
21+
/// Is the attribute identifier generally known for any syntax?
22+
Generic,
23+
/// Is the identifier known as a GNU-style attribute?
24+
GNU,
25+
/// Is the identifier known as a __declspec-style attribute?
26+
Declspec,
27+
// Is the identifier known as a C++-style attribute?
28+
CXX
29+
};
30+
31+
/// \brief Return true if we recognize and implement the attribute specified by
32+
/// the given information.
33+
bool HasAttribute(AttrSyntax Syntax, const IdentifierInfo *Scope,
34+
const IdentifierInfo *Attr, const llvm::Triple &T,
35+
const LangOptions &LangOpts);
36+
37+
} // end namespace clang
38+
39+
#endif // LLVM_CLANG_BASIC_ATTRIBUTES_H

include/clang/Basic/CMakeLists.txt

+6
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ clang_tablegen(AttrList.inc -gen-clang-attr-list
2828
SOURCE Attr.td
2929
TARGET ClangAttrList)
3030

31+
clang_tablegen(AttrHasAttributeImpl.inc -gen-clang-attr-has-attribute-impl
32+
-I ${CMAKE_CURRENT_SOURCE_DIR}/../../
33+
SOURCE Attr.td
34+
TARGET ClangAttrHasAttributeImpl
35+
)
36+
3137
# ARM NEON
3238
clang_tablegen(arm_neon.inc -gen-arm-neon-sema
3339
-I ${CMAKE_CURRENT_SOURCE_DIR}/../../

include/clang/Basic/Makefile

+7
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ BUILT_SOURCES = \
66
DiagnosticFrontendKinds.inc DiagnosticLexKinds.inc \
77
DiagnosticParseKinds.inc DiagnosticSemaKinds.inc \
88
DiagnosticSerializationKinds.inc \
9+
AttrHasAttributeImpl.inc \
910
DiagnosticIndexName.inc DiagnosticGroups.inc AttrList.inc arm_neon.inc \
1011
Version.inc
1112

@@ -48,6 +49,12 @@ $(ObjDir)/AttrList.inc.tmp : Attr.td $(CLANG_TBLGEN) $(ObjDir)/.dir
4849
$(Verb) $(ClangTableGen) -gen-clang-attr-list -o $(call SYSPATH, $@) \
4950
-I $(PROJ_SRC_DIR)/../.. $<
5051

52+
$(ObjDir)/AttrHasAttributeImpl.inc.tmp : Attr.td $(CLANG_TBLGEN) \
53+
$(ObjDir)/.dir
54+
$(Echo) "Building Clang __has_attribute implementation with tblgen"
55+
$(Verb) $(ClangTableGen) -gen-clang-attr-has-attribute-impl -o $(call SYSPATH, $@) \
56+
-I $(PROJ_SRC_DIR)/../../ $<
57+
5158
$(ObjDir)/arm_neon.inc.tmp : arm_neon.td $(CLANG_TBLGEN) $(ObjDir)/.dir
5259
$(Echo) "Building Clang arm_neon.inc with tblgen"
5360
$(Verb) $(ClangTableGen) -gen-arm-neon-sema -o $(call SYSPATH, $@) \

include/clang/CMakeLists.txt

-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
add_subdirectory(AST)
22
add_subdirectory(Basic)
33
add_subdirectory(Driver)
4-
add_subdirectory(Lex)
54
add_subdirectory(Parse)
65
add_subdirectory(Sema)
76
add_subdirectory(Serialization)

include/clang/Lex/CMakeLists.txt

-5
This file was deleted.

include/clang/Lex/Makefile

-13
This file was deleted.

include/clang/Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
CLANG_LEVEL := ../..
2-
DIRS := AST Basic Driver Lex Parse Sema Serialization
2+
DIRS := AST Basic Driver Parse Sema Serialization
33

44
include $(CLANG_LEVEL)/Makefile
55

lib/Basic/Attributes.cpp

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#include "clang/Basic/Attributes.h"
2+
#include "clang/Basic/IdentifierTable.h"
3+
#include "llvm/ADT/StringSwitch.h"
4+
using namespace clang;
5+
6+
bool clang::HasAttribute(AttrSyntax Syntax, const IdentifierInfo *Scope,
7+
const IdentifierInfo *Attr, const llvm::Triple &T,
8+
const LangOptions &LangOpts) {
9+
StringRef Name = Attr->getName();
10+
// Normalize the attribute name, __foo__ becomes foo.
11+
if (Name.size() >= 4 && Name.startswith("__") && Name.endswith("__"))
12+
Name = Name.substr(2, Name.size() - 4);
13+
14+
#include "clang/Basic/AttrHasAttributeImpl.inc"
15+
16+
return false;
17+
}

lib/Basic/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ set(LLVM_LINK_COMPONENTS
44
)
55

66
add_clang_library(clangBasic
7+
Attributes.cpp
78
Builtins.cpp
89
CharInfo.cpp
910
Diagnostic.cpp

lib/Lex/PPMacroExpansion.cpp

+3-15
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
//===----------------------------------------------------------------------===//
1414

1515
#include "clang/Lex/Preprocessor.h"
16+
#include "clang/Basic/Attributes.h"
1617
#include "clang/Basic/FileManager.h"
1718
#include "clang/Basic/SourceManager.h"
1819
#include "clang/Basic/TargetInfo.h"
@@ -1047,20 +1048,6 @@ static bool HasExtension(const Preprocessor &PP, const IdentifierInfo *II) {
10471048
.Default(false);
10481049
}
10491050

1050-
/// HasAttribute - Return true if we recognize and implement the attribute
1051-
/// specified by the given identifier.
1052-
static bool HasAttribute(const IdentifierInfo *II, const llvm::Triple &T) {
1053-
StringRef Name = II->getName();
1054-
// Normalize the attribute name, __foo__ becomes foo.
1055-
if (Name.size() >= 4 && Name.startswith("__") && Name.endswith("__"))
1056-
Name = Name.substr(2, Name.size() - 4);
1057-
1058-
// FIXME: Do we need to handle namespaces here?
1059-
return llvm::StringSwitch<bool>(Name)
1060-
#include "clang/Lex/AttrSpellings.inc"
1061-
.Default(false);
1062-
}
1063-
10641051
/// EvaluateHasIncludeCommon - Process a '__has_include("path")'
10651052
/// or '__has_include_next("path")' expression.
10661053
/// Returns true if successful.
@@ -1399,7 +1386,8 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
13991386
// Check for a builtin is trivial.
14001387
Value = FeatureII->getBuiltinID() != 0;
14011388
} else if (II == Ident__has_attribute)
1402-
Value = HasAttribute(FeatureII, getTargetInfo().getTriple());
1389+
Value = HasAttribute(AttrSyntax::Generic, nullptr, FeatureII,
1390+
getTargetInfo().getTriple(), getLangOpts());
14031391
else if (II == Ident__has_extension)
14041392
Value = HasExtension(*this, FeatureII);
14051393
else {

utils/TableGen/ClangAttrEmitter.cpp

+75-15
Original file line numberDiff line numberDiff line change
@@ -1720,22 +1720,16 @@ void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS) {
17201720
OS << " }\n";
17211721
}
17221722

1723-
// Emits the list of spellings for attributes.
1724-
void EmitClangAttrSpellingList(RecordKeeper &Records, raw_ostream &OS) {
1725-
emitSourceFileHeader("llvm::StringSwitch code to match attributes based on "
1726-
"the target triple, T", OS);
1727-
1728-
std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1729-
1730-
for (auto I : Attrs) {
1731-
Record &Attr = *I;
1732-
1723+
static void GenerateHasAttrSpellingStringSwitch(
1724+
const std::vector<Record *> &Attrs, raw_ostream &OS,
1725+
const std::string &Variety = "", const std::string &Scope = "") {
1726+
for (const auto *Attr : Attrs) {
17331727
// It is assumed that there will be an llvm::Triple object named T within
17341728
// scope that can be used to determine whether the attribute exists in
17351729
// a given target.
17361730
std::string Test;
1737-
if (Attr.isSubClassOf("TargetSpecificAttr")) {
1738-
const Record *R = Attr.getValueAsDef("Target");
1731+
if (Attr->isSubClassOf("TargetSpecificAttr")) {
1732+
const Record *R = Attr->getValueAsDef("Target");
17391733
std::vector<std::string> Arches = R->getValueAsListOfStrings("Arches");
17401734

17411735
Test += "(";
@@ -1760,13 +1754,79 @@ void EmitClangAttrSpellingList(RecordKeeper &Records, raw_ostream &OS) {
17601754
}
17611755
Test += ")";
17621756
}
1763-
} else
1757+
1758+
// If this is the C++11 variety, also add in the LangOpts test.
1759+
if (Variety == "CXX11")
1760+
Test += " && LangOpts.CPlusPlus11";
1761+
} else if (Variety == "CXX11")
1762+
// C++11 mode should be checked against LangOpts, which is presumed to be
1763+
// present in the caller.
1764+
Test = "LangOpts.CPlusPlus11";
1765+
else
17641766
Test = "true";
17651767

1766-
std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
1768+
std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Attr);
17671769
for (const auto &S : Spellings)
1768-
OS << ".Case(\"" << S.name() << "\", " << Test << ")\n";
1770+
if (Variety.empty() || (Variety == S.variety() &&
1771+
(Scope.empty() || Scope == S.nameSpace())))
1772+
OS << " .Case(\"" << S.name() << "\", " << Test << ")\n";
1773+
}
1774+
OS << " .Default(false);\n";
1775+
}
1776+
1777+
// Emits the list of spellings for attributes.
1778+
void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
1779+
emitSourceFileHeader("Code to implement the __has_attribute logic", OS);
1780+
1781+
// Separate all of the attributes out into four group: generic, C++11, GNU,
1782+
// and declspecs. Then generate a big switch statement for each of them.
1783+
std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
1784+
std::vector<Record *> Declspec, GNU;
1785+
std::map<std::string, std::vector<Record *>> CXX;
1786+
1787+
// Walk over the list of all attributes, and split them out based on the
1788+
// spelling variety.
1789+
for (auto *R : Attrs) {
1790+
std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*R);
1791+
for (const auto &SI : Spellings) {
1792+
std::string Variety = SI.variety();
1793+
if (Variety == "GNU")
1794+
GNU.push_back(R);
1795+
else if (Variety == "Declspec")
1796+
Declspec.push_back(R);
1797+
else if (Variety == "CXX11") {
1798+
CXX[SI.nameSpace()].push_back(R);
1799+
}
1800+
}
1801+
}
1802+
1803+
OS << "switch (Syntax) {\n";
1804+
OS << "case AttrSyntax::Generic:\n";
1805+
OS << " return llvm::StringSwitch<bool>(Name)\n";
1806+
GenerateHasAttrSpellingStringSwitch(Attrs, OS);
1807+
OS << "case AttrSyntax::GNU:\n";
1808+
OS << " return llvm::StringSwitch<bool>(Name)\n";
1809+
GenerateHasAttrSpellingStringSwitch(GNU, OS, "GNU");
1810+
OS << "case AttrSyntax::Declspec:\n";
1811+
OS << " return llvm::StringSwitch<bool>(Name)\n";
1812+
GenerateHasAttrSpellingStringSwitch(Declspec, OS, "Declspec");
1813+
OS << "case AttrSyntax::CXX: {\n";
1814+
// C++11-style attributes are further split out based on the Scope.
1815+
for (std::map<std::string, std::vector<Record *>>::iterator I = CXX.begin(),
1816+
E = CXX.end();
1817+
I != E; ++I) {
1818+
if (I != CXX.begin())
1819+
OS << " else ";
1820+
if (I->first.empty())
1821+
OS << "if (!Scope || Scope->getName() == \"\") {\n";
1822+
else
1823+
OS << "if (Scope->getName() == \"" << I->first << "\") {\n";
1824+
OS << " return llvm::StringSwitch<bool>(Name)\n";
1825+
GenerateHasAttrSpellingStringSwitch(I->second, OS, "CXX11", I->first);
1826+
OS << "}";
17691827
}
1828+
OS << "\n}\n";
1829+
OS << "}\n";
17701830
}
17711831

17721832
void EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS) {

utils/TableGen/TableGen.cpp

+5-4
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ enum ActionType {
2929
GenClangAttrList,
3030
GenClangAttrPCHRead,
3131
GenClangAttrPCHWrite,
32-
GenClangAttrSpellingList,
32+
GenClangAttrHasAttributeImpl,
3333
GenClangAttrSpellingListIndex,
3434
GenClangAttrASTVisitor,
3535
GenClangAttrTemplateInstantiate,
@@ -72,7 +72,8 @@ cl::opt<ActionType> Action(
7272
"Generate clang PCH attribute reader"),
7373
clEnumValN(GenClangAttrPCHWrite, "gen-clang-attr-pch-write",
7474
"Generate clang PCH attribute writer"),
75-
clEnumValN(GenClangAttrSpellingList, "gen-clang-attr-spelling-list",
75+
clEnumValN(GenClangAttrHasAttributeImpl,
76+
"gen-clang-attr-has-attribute-impl",
7677
"Generate a clang attribute spelling list"),
7778
clEnumValN(GenClangAttrSpellingListIndex,
7879
"gen-clang-attr-spelling-index",
@@ -159,8 +160,8 @@ bool ClangTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
159160
case GenClangAttrPCHWrite:
160161
EmitClangAttrPCHWrite(Records, OS);
161162
break;
162-
case GenClangAttrSpellingList:
163-
EmitClangAttrSpellingList(Records, OS);
163+
case GenClangAttrHasAttributeImpl:
164+
EmitClangAttrHasAttrImpl(Records, OS);
164165
break;
165166
case GenClangAttrSpellingListIndex:
166167
EmitClangAttrSpellingListIndex(Records, OS);

utils/TableGen/TableGenBackends.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ void EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS);
3535
void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS);
3636
void EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS);
3737
void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS);
38-
void EmitClangAttrSpellingList(RecordKeeper &Records, raw_ostream &OS);
38+
void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS);
3939
void EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS);
4040
void EmitClangAttrASTVisitor(RecordKeeper &Records, raw_ostream &OS);
4141
void EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS);

0 commit comments

Comments
 (0)