r198896 - Removing the notion of TargetAttributesSema and replacing it with one where the parsed attributes are responsible for knowing their target-specific nature, instead of letting Sema figure it out. This is necessary so that __has_attribute can eventually determine whether a parsed attribute applies to the given target or not.
Aaron Ballman
aaron at aaronballman.com
Thu Jan 9 14:48:33 PST 2014
Author: aaronballman
Date: Thu Jan 9 16:48:32 2014
New Revision: 198896
URL: http://llvm.org/viewvc/llvm-project?rev=198896&view=rev
Log:
Removing the notion of TargetAttributesSema and replacing it with one where the parsed attributes are responsible for knowing their target-specific nature, instead of letting Sema figure it out. This is necessary so that __has_attribute can eventually determine whether a parsed attribute applies to the given target or not.
Removed:
cfe/trunk/lib/Sema/TargetAttributesSema.cpp
cfe/trunk/lib/Sema/TargetAttributesSema.h
Modified:
cfe/trunk/include/clang/Basic/Attr.td
cfe/trunk/include/clang/Sema/AttributeList.h
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Sema/AttributeList.cpp
cfe/trunk/lib/Sema/CMakeLists.txt
cfe/trunk/lib/Sema/Sema.cpp
cfe/trunk/lib/Sema/SemaDeclAttr.cpp
cfe/trunk/lib/Sema/SemaStmtAttr.cpp
cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
Modified: cfe/trunk/include/clang/Basic/Attr.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=198896&r1=198895&r2=198896&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Attr.td (original)
+++ cfe/trunk/include/clang/Basic/Attr.td Thu Jan 9 16:48:32 2014
@@ -142,6 +142,21 @@ def MicrosoftExt : LangOpt<"MicrosoftExt
def Borland : LangOpt<"Borland">;
def CUDA : LangOpt<"CUDA">;
+// Defines targets for target-specific attributes. The list of strings should
+// specify architectures for which the target applies, based off the ArchType
+// enumeration in Triple.h.
+class TargetArch<list<string> arches> {
+ list<string> Arches = arches;
+ list<string> OSes;
+}
+def TargetARM : TargetArch<["arm", "thumb"]>;
+def TargetMSP430 : TargetArch<["msp430"]>;
+def TargetX86 : TargetArch<["x86"]>;
+def TargetX86Win : TargetArch<["x86", "x86_64"]> {
+ let OSes = ["Win32", "MinGW32"];
+}
+def TargetMips : TargetArch<["mips", "mipsel"]>;
+
class Attr {
// The various ways in which an attribute can be spelled in source
list<Spelling> Spellings;
@@ -187,10 +202,10 @@ class TypeAttr : Attr {
/// An inheritable attribute is inherited by later redeclarations.
class InheritableAttr : Attr;
-/// A target-specific attribute that is meant to be processed via
-/// TargetAttributesSema::ProcessDeclAttribute. This class is meant to be used
-/// as a mixin with InheritableAttr or Attr depending on the attribute's needs.
-class TargetSpecificAttr {
+/// A target-specific attribute. This class is meant to be used as a mixin
+/// with InheritableAttr or Attr depending on the attribute's needs.
+class TargetSpecificAttr<TargetArch target> {
+ TargetArch Target = target;
// Attributes are generally required to have unique spellings for their names
// so that the parser can determine what kind of attribute it has parsed.
// However, target-specific attributes are special in that the attribute only
@@ -269,7 +284,7 @@ def Annotate : InheritableParamAttr {
let Args = [StringArgument<"Annotation">];
}
-def ARMInterrupt : InheritableAttr, TargetSpecificAttr {
+def ARMInterrupt : InheritableAttr, TargetSpecificAttr<TargetARM> {
// NOTE: If you add any additional spellings, MSP430Interrupt's spellings
// must match.
let Spellings = [GNU<"interrupt">];
@@ -547,7 +562,7 @@ def MSABI : InheritableAttr {
// let Subjects = [Function, ObjCMethod];
}
-def MSP430Interrupt : InheritableAttr, TargetSpecificAttr {
+def MSP430Interrupt : InheritableAttr, TargetSpecificAttr<TargetMSP430> {
// NOTE: If you add any additional spellings, ARMInterrupt's spellings must
// match.
let Spellings = [GNU<"interrupt">];
@@ -556,7 +571,7 @@ def MSP430Interrupt : InheritableAttr, T
let HasCustomParsing = 1;
}
-def Mips16 : InheritableAttr, TargetSpecificAttr {
+def Mips16 : InheritableAttr, TargetSpecificAttr<TargetMips> {
let Spellings = [GNU<"mips16">, CXX11<"gnu", "mips16">];
let Subjects = SubjectList<[Function], ErrorDiag>;
}
@@ -600,7 +615,7 @@ def NoInline : InheritableAttr {
let Subjects = SubjectList<[Function]>;
}
-def NoMips16 : InheritableAttr, TargetSpecificAttr {
+def NoMips16 : InheritableAttr, TargetSpecificAttr<TargetMips> {
let Spellings = [GNU<"nomips16">, CXX11<"gnu", "nomips16">];
let Subjects = SubjectList<[Function], ErrorDiag>;
}
@@ -952,8 +967,11 @@ def WeakRef : InheritableAttr {
let Subjects = SubjectList<[Var, Function], ErrorDiag>;
}
-def X86ForceAlignArgPointer : InheritableAttr, TargetSpecificAttr {
- let Spellings = [];
+def X86ForceAlignArgPointer : InheritableAttr, TargetSpecificAttr<TargetX86> {
+ let Spellings = [GNU<"force_align_arg_pointer">];
+ // Technically, this appertains to a FunctionDecl, but the target-specific
+ // code silently allows anything function-like (such as typedefs or function
+ // pointers), but does not apply the attribute to them.
}
// Attribute to disable AddressSanitizer (or equivalent) checks.
@@ -1232,12 +1250,12 @@ def MsStruct : InheritableAttr {
let Subjects = SubjectList<[Record]>;
}
-def DLLExport : InheritableAttr, TargetSpecificAttr {
+def DLLExport : InheritableAttr, TargetSpecificAttr<TargetX86Win> {
let Spellings = [Declspec<"dllexport">];
let Subjects = SubjectList<[Function, Var]>;
}
-def DLLImport : InheritableAttr, TargetSpecificAttr {
+def DLLImport : InheritableAttr, TargetSpecificAttr<TargetX86Win> {
let Spellings = [Declspec<"dllimport">];
// Technically, the subjects for DllImport are Function and Var, but there is
// custom semantic handling required when MicrosoftExt is true.
Modified: cfe/trunk/include/clang/Sema/AttributeList.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/AttributeList.h?rev=198896&r1=198895&r2=198896&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/AttributeList.h (original)
+++ cfe/trunk/include/clang/Sema/AttributeList.h Thu Jan 9 16:48:32 2014
@@ -20,6 +20,7 @@
#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>
@@ -484,11 +485,15 @@ public:
/// to pretty print itself.
unsigned getAttributeSpellingListIndex() const;
+ bool isTargetSpecificAttr() const;
+ bool isTypeAttr() const;
+
bool hasCustomParsing() const;
unsigned getMinArgs() const;
unsigned getMaxArgs() const;
bool diagnoseAppertainsTo(class Sema &S, const Decl *D) const;
bool diagnoseLangOpts(class Sema &S) const;
+ bool existsInTarget(llvm::Triple T) const;
};
/// A factory, from which one makes pools, from which one creates
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=198896&r1=198895&r2=198896&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Thu Jan 9 16:48:32 2014
@@ -152,7 +152,6 @@ namespace clang {
class Stmt;
class StringLiteral;
class SwitchStmt;
- class TargetAttributesSema;
class TemplateArgument;
class TemplateArgumentList;
class TemplateArgumentLoc;
@@ -204,7 +203,6 @@ typedef std::pair<llvm::PointerUnion<con
class Sema {
Sema(const Sema &) LLVM_DELETED_FUNCTION;
void operator=(const Sema &) LLVM_DELETED_FUNCTION;
- mutable const TargetAttributesSema* TheTargetAttributesSema;
///\brief Source of additional semantic information.
ExternalSemaSource *ExternalSource;
@@ -875,7 +873,6 @@ public:
DiagnosticsEngine &getDiagnostics() const { return Diags; }
SourceManager &getSourceManager() const { return SourceMgr; }
- const TargetAttributesSema &getTargetAttributesSema() const;
Preprocessor &getPreprocessor() const { return PP; }
ASTContext &getASTContext() const { return Context; }
ASTConsumer &getASTConsumer() const { return Consumer; }
Modified: cfe/trunk/lib/Sema/AttributeList.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/AttributeList.cpp?rev=198896&r1=198895&r2=198896&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/AttributeList.cpp (original)
+++ cfe/trunk/lib/Sema/AttributeList.cpp Thu Jan 9 16:48:32 2014
@@ -156,10 +156,13 @@ struct ParsedAttrInfo {
unsigned NumArgs : 4;
unsigned OptArgs : 4;
unsigned HasCustomParsing : 1;
+ unsigned IsTargetSpecific : 1;
+ unsigned IsType : 1;
bool (*DiagAppertainsToDecl)(Sema &S, const AttributeList &Attr,
const Decl *);
bool (*DiagLangOpts)(Sema &S, const AttributeList &Attr);
+ bool (*ExistsInTarget)(llvm::Triple T);
};
namespace {
@@ -189,3 +192,15 @@ bool AttributeList::diagnoseAppertainsTo
bool AttributeList::diagnoseLangOpts(Sema &S) const {
return getInfo(*this).DiagLangOpts(S, *this);
}
+
+bool AttributeList::isTargetSpecificAttr() const {
+ return getInfo(*this).IsTargetSpecific;
+}
+
+bool AttributeList::isTypeAttr() const {
+ return getInfo(*this).IsType;
+}
+
+bool AttributeList::existsInTarget(llvm::Triple T) const {
+ return getInfo(*this).ExistsInTarget(T);
+}
Modified: cfe/trunk/lib/Sema/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/CMakeLists.txt?rev=198896&r1=198895&r2=198896&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/CMakeLists.txt (original)
+++ cfe/trunk/lib/Sema/CMakeLists.txt Thu Jan 9 16:48:32 2014
@@ -47,7 +47,6 @@ add_clang_library(clangSema
SemaTemplateInstantiateDecl.cpp
SemaTemplateVariadic.cpp
SemaType.cpp
- TargetAttributesSema.cpp
TypeLocBuilder.cpp
)
Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=198896&r1=198895&r2=198896&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Thu Jan 9 16:48:32 2014
@@ -13,7 +13,6 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
-#include "TargetAttributesSema.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTDiagnostic.h"
#include "clang/AST/DeclCXX.h"
@@ -70,7 +69,7 @@ void Sema::ActOnTranslationUnitScope(Sco
Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
TranslationUnitKind TUKind,
CodeCompleteConsumer *CodeCompleter)
- : TheTargetAttributesSema(0), ExternalSource(0),
+ : ExternalSource(0),
isMultiplexExternalSource(false), FPFeatures(pp.getLangOpts()),
LangOpts(pp.getLangOpts()), PP(pp), Context(ctxt), Consumer(consumer),
Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
@@ -209,7 +208,6 @@ Sema::~Sema() {
delete I->second;
if (PackContext) FreePackedContext();
if (VisContext) FreeVisContext();
- delete TheTargetAttributesSema;
MSStructPragmaOn = false;
// Kill all the active scopes.
for (unsigned I = 1, E = FunctionScopes.size(); I != E; ++I)
Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=198896&r1=198895&r2=198896&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Thu Jan 9 16:48:32 2014
@@ -12,7 +12,6 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
-#include "TargetAttributesSema.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclCXX.h"
@@ -205,7 +204,6 @@ static bool checkAttributeNumArgs(Sema &
return true;
}
-
/// \brief Check if the attribute has at least as many args as Num. May
/// output an error.
static bool checkAttributeAtLeastNumArgs(Sema &S, const AttributeList &Attr,
@@ -3174,8 +3172,7 @@ bool Sema::CheckCallingConvAttr(const At
return true;
}
- // TODO: diagnose uses of these conventions on the wrong target. Or, better
- // move to TargetAttributesSema one day.
+ // TODO: diagnose uses of these conventions on the wrong target.
switch (attr.getKind()) {
case AttributeList::AT_CDecl: CC = CC_C; break;
case AttributeList::AT_FastCall: CC = CC_X86FastCall; break;
@@ -3712,6 +3709,179 @@ static void handleUuidAttr(Sema &S, Decl
Attr.getAttributeSpellingListIndex()));
}
+static void handleARMInterruptAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ // Check the attribute arguments.
+ if (Attr.getNumArgs() > 1) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments)
+ << Attr.getName() << 1;
+ return;
+ }
+
+ StringRef Str;
+ SourceLocation ArgLoc;
+
+ if (Attr.getNumArgs() == 0)
+ Str = "";
+ else if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str, &ArgLoc))
+ return;
+
+ ARMInterruptAttr::InterruptType Kind;
+ if (!ARMInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
+ << Attr.getName() << Str << ArgLoc;
+ return;
+ }
+
+ unsigned Index = Attr.getAttributeSpellingListIndex();
+ D->addAttr(::new (S.Context)
+ ARMInterruptAttr(Attr.getLoc(), S.Context, Kind, Index));
+}
+
+static void handleMSP430InterruptAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ if (!checkAttributeNumArgs(S, Attr, 1))
+ return;
+
+ if (!Attr.isArgExpr(0)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << Attr.getName()
+ << AANT_ArgumentIntegerConstant;
+ return;
+ }
+
+ // FIXME: Check for decl - it should be void ()(void).
+
+ Expr *NumParamsExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
+ llvm::APSInt NumParams(32);
+ if (!NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
+ << Attr.getName() << AANT_ArgumentIntegerConstant
+ << NumParamsExpr->getSourceRange();
+ return;
+ }
+
+ unsigned Num = NumParams.getLimitedValue(255);
+ if ((Num & 1) || Num > 30) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
+ << Attr.getName() << (int)NumParams.getSExtValue()
+ << NumParamsExpr->getSourceRange();
+ return;
+ }
+
+ D->addAttr(::new (S.Context) MSP430InterruptAttr(Attr.getLoc(), S.Context, Num));
+ D->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context));
+}
+
+static void handleInterruptAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ // Dispatch the interrupt attribute based on the current target.
+ if (S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::msp430)
+ handleMSP430InterruptAttr(S, D, Attr);
+ else
+ handleARMInterruptAttr(S, D, Attr);
+}
+
+static void handleX86ForceAlignArgPointerAttr(Sema &S, Decl *D,
+ const AttributeList& Attr) {
+ // If we try to apply it to a function pointer, don't warn, but don't
+ // do anything, either. It doesn't matter anyway, because there's nothing
+ // special about calling a force_align_arg_pointer function.
+ ValueDecl *VD = dyn_cast<ValueDecl>(D);
+ if (VD && VD->getType()->isFunctionPointerType())
+ return;
+ // Also don't warn on function pointer typedefs.
+ TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D);
+ if (TD && (TD->getUnderlyingType()->isFunctionPointerType() ||
+ TD->getUnderlyingType()->isFunctionType()))
+ return;
+ // Attribute can only be applied to function types.
+ if (!isa<FunctionDecl>(D)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << /* function */0;
+ return;
+ }
+
+ D->addAttr(::new (S.Context) X86ForceAlignArgPointerAttr(Attr.getRange(),
+ S.Context));
+}
+
+DLLImportAttr *Sema::mergeDLLImportAttr(Decl *D, SourceRange Range,
+ unsigned AttrSpellingListIndex) {
+ if (D->hasAttr<DLLExportAttr>()) {
+ Diag(Range.getBegin(), diag::warn_attribute_ignored) << "dllimport";
+ return NULL;
+ }
+
+ if (D->hasAttr<DLLImportAttr>())
+ return NULL;
+
+ if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ if (VD->hasDefinition()) {
+ // dllimport cannot be applied to definitions.
+ Diag(D->getLocation(), diag::warn_attribute_invalid_on_definition)
+ << "dllimport";
+ return NULL;
+ }
+ }
+
+ return ::new (Context)DLLImportAttr(Range, Context,
+ AttrSpellingListIndex);
+}
+
+static void handleDLLImportAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ // Attribute can be applied only to functions or variables.
+ FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
+ if (!FD && !isa<VarDecl>(D)) {
+ // Apparently Visual C++ thinks it is okay to not emit a warning
+ // in this case, so only emit a warning when -fms-extensions is not
+ // specified.
+ if (!S.getLangOpts().MicrosoftExt)
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 2 /*variable and function*/;
+ return;
+ }
+
+ // Currently, the dllimport attribute is ignored for inlined functions.
+ // Warning is emitted.
+ if (FD && FD->isInlineSpecified()) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+ return;
+ }
+
+ unsigned Index = Attr.getAttributeSpellingListIndex();
+ DLLImportAttr *NewAttr = S.mergeDLLImportAttr(D, Attr.getRange(), Index);
+ if (NewAttr)
+ D->addAttr(NewAttr);
+}
+
+DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D, SourceRange Range,
+ unsigned AttrSpellingListIndex) {
+ if (DLLImportAttr *Import = D->getAttr<DLLImportAttr>()) {
+ Diag(Import->getLocation(), diag::warn_attribute_ignored) << "dllimport";
+ D->dropAttr<DLLImportAttr>();
+ }
+
+ if (D->hasAttr<DLLExportAttr>())
+ return NULL;
+
+ return ::new (Context)DLLExportAttr(Range, Context,
+ AttrSpellingListIndex);
+}
+
+static void handleDLLExportAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ // Currently, the dllexport attribute is ignored for inlined functions, unless
+ // the -fkeep-inline-functions flag has been used. Warning is emitted;
+ if (isa<FunctionDecl>(D) && cast<FunctionDecl>(D)->isInlineSpecified()) {
+ // FIXME: ... unless the -fkeep-inline-functions flag has been used.
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+ return;
+ }
+
+ unsigned Index = Attr.getAttributeSpellingListIndex();
+ DLLExportAttr *NewAttr = S.mergeDLLExportAttr(D, Attr.getRange(), Index);
+ if (NewAttr)
+ D->addAttr(NewAttr);
+}
+
/// Handles semantic checking for features that are common to all attributes,
/// such as checking whether a parameter was properly specified, or the correct
/// number of arguments were passed, etc.
@@ -3723,8 +3893,7 @@ static bool handleCommonAttributeFeature
// We also bail on unknown and ignored attributes because those are handled
// as part of the target-specific handling logic.
if (Attr.hasCustomParsing() ||
- Attr.getKind() == AttributeList::UnknownAttribute ||
- Attr.getKind() == AttributeList::IgnoredAttribute)
+ Attr.getKind() == AttributeList::UnknownAttribute)
return false;
// Check whether the attribute requires specific language extensions to be
@@ -3755,7 +3924,7 @@ static bool handleCommonAttributeFeature
static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
const AttributeList &Attr,
bool IncludeCXX11Attributes) {
- if (Attr.isInvalid())
+ if (Attr.isInvalid() || Attr.getKind() == AttributeList::IgnoredAttribute)
return;
// Ignore C++11 attributes on declarator chunks: they appertain to the type
@@ -3763,28 +3932,42 @@ static void ProcessDeclAttribute(Sema &S
if (Attr.isCXX11Attribute() && !IncludeCXX11Attributes)
return;
+ // Unknown attributes are automatically warned on. Target-specific attributes
+ // 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())) {
+ S.Diag(Attr.getLoc(), Attr.isDeclspecAttribute() ?
+ diag::warn_unhandled_ms_attribute_ignored :
+ diag::warn_unknown_attribute_ignored) << Attr.getName();
+ return;
+ }
+
if (handleCommonAttributeFeatures(S, scope, D, Attr))
return;
switch (Attr.getKind()) {
+ default:
+ // Type attributes are handled elsewhere; silently move on.
+ assert(Attr.isTypeAttr() && "Non-type attribute not handled");
+ break;
+ case AttributeList::AT_Interrupt:
+ handleInterruptAttr(S, D, Attr); break;
+ case AttributeList::AT_X86ForceAlignArgPointer:
+ handleX86ForceAlignArgPointerAttr(S, D, Attr); break;
+ case AttributeList::AT_DLLExport:
+ handleDLLExportAttr(S, D, Attr); break;
+ case AttributeList::AT_DLLImport:
+ handleDLLImportAttr(S, D, Attr); break;
+ case AttributeList::AT_Mips16:
+ handleSimpleAttribute<Mips16Attr>(S, D, Attr); break;
+ case AttributeList::AT_NoMips16:
+ handleSimpleAttribute<NoMips16Attr>(S, D, Attr); break;
case AttributeList::AT_IBAction:
handleSimpleAttribute<IBActionAttr>(S, D, Attr); break;
case AttributeList::AT_IBOutlet: handleIBOutlet(S, D, Attr); break;
case AttributeList::AT_IBOutletCollection:
handleIBOutletCollection(S, D, Attr); break;
- case AttributeList::AT_AddressSpace:
- case AttributeList::AT_ObjCGC:
- case AttributeList::AT_VectorSize:
- case AttributeList::AT_NeonVectorType:
- case AttributeList::AT_NeonPolyVectorType:
- case AttributeList::AT_Ptr32:
- case AttributeList::AT_Ptr64:
- case AttributeList::AT_SPtr:
- case AttributeList::AT_UPtr:
- case AttributeList::AT_Regparm:
- // Ignore these, these are type attributes, handled by
- // ProcessTypeAttributes.
- break;
case AttributeList::AT_Alias: handleAliasAttr (S, D, Attr); break;
case AttributeList::AT_Aligned: handleAlignedAttr (S, D, Attr); break;
case AttributeList::AT_AlwaysInline:
@@ -3946,9 +4129,6 @@ static void ProcessDeclAttribute(Sema &S
case AttributeList::AT_NoDebug: handleNoDebugAttr (S, D, Attr); break;
case AttributeList::AT_NoInline:
handleSimpleAttribute<NoInlineAttr>(S, D, Attr); break;
- case AttributeList::IgnoredAttribute:
- // Just ignore
- break;
case AttributeList::AT_NoInstrumentFunction: // Interacts with -pg.
handleSimpleAttribute<NoInstrumentFunctionAttr>(S, D, Attr); break;
case AttributeList::AT_StdCall:
@@ -4078,15 +4258,6 @@ static void ProcessDeclAttribute(Sema &S
case AttributeList::AT_TypeTagForDatatype:
handleTypeTagForDatatypeAttr(S, D, Attr);
break;
-
- default:
- // Ask target about the attribute.
- const TargetAttributesSema &TargetAttrs = S.getTargetAttributesSema();
- if (!TargetAttrs.ProcessDeclAttribute(scope, D, Attr, S))
- S.Diag(Attr.getLoc(), Attr.isDeclspecAttribute() ?
- diag::warn_unhandled_ms_attribute_ignored :
- diag::warn_unknown_attribute_ignored) << Attr.getName();
- break;
}
}
Modified: cfe/trunk/lib/Sema/SemaStmtAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmtAttr.cpp?rev=198896&r1=198895&r2=198896&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaStmtAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmtAttr.cpp Thu Jan 9 16:48:32 2014
@@ -12,7 +12,6 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
-#include "TargetAttributesSema.h"
#include "clang/AST/ASTContext.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Lexer.h"
Removed: cfe/trunk/lib/Sema/TargetAttributesSema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TargetAttributesSema.cpp?rev=198895&view=auto
==============================================================================
--- cfe/trunk/lib/Sema/TargetAttributesSema.cpp (original)
+++ cfe/trunk/lib/Sema/TargetAttributesSema.cpp (removed)
@@ -1,295 +0,0 @@
-//===-- TargetAttributesSema.cpp - Encapsulate target attributes-*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains semantic analysis implementation for target-specific
-// attributes.
-//
-//===----------------------------------------------------------------------===//
-
-#include "TargetAttributesSema.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/Basic/TargetInfo.h"
-#include "clang/Sema/SemaInternal.h"
-#include "llvm/ADT/Triple.h"
-
-using namespace clang;
-
-TargetAttributesSema::~TargetAttributesSema() {}
-bool TargetAttributesSema::ProcessDeclAttribute(Scope *scope, Decl *D,
- const AttributeList &Attr, Sema &S) const {
- return false;
-}
-
-static void HandleARMInterruptAttr(Decl *d,
- const AttributeList &Attr, Sema &S) {
- // Check the attribute arguments.
- if (Attr.getNumArgs() > 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments)
- << Attr.getName() << 1;
- return;
- }
-
- StringRef Str;
- SourceLocation ArgLoc;
-
- if (Attr.getNumArgs() == 0)
- Str = "";
- else if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str, &ArgLoc))
- return;
-
- ARMInterruptAttr::InterruptType Kind;
- if (!ARMInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
- << Attr.getName() << Str << ArgLoc;
- return;
- }
-
- unsigned Index = Attr.getAttributeSpellingListIndex();
- d->addAttr(::new (S.Context)
- ARMInterruptAttr(Attr.getLoc(), S.Context, Kind, Index));
-}
-
-namespace {
- class ARMAttributesSema : public TargetAttributesSema {
- public:
- ARMAttributesSema() { }
- bool ProcessDeclAttribute(Scope *scope, Decl *D,
- const AttributeList &Attr, Sema &S) const {
- if (Attr.getKind() == AttributeList::AT_Interrupt) {
- HandleARMInterruptAttr(D, Attr, S);
- return true;
- }
- return false;
- }
- };
-}
-
-static void HandleMSP430InterruptAttr(Decl *d,
- const AttributeList &Attr, Sema &S) {
- if (Attr.getNumArgs() != 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << Attr.getName() << 1;
- return;
- }
-
- if (!Attr.isArgExpr(0)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << Attr.getName()
- << AANT_ArgumentIntegerConstant;
- return;
- }
-
- // FIXME: Check for decl - it should be void ()(void).
- Expr *NumParamsExpr = Attr.getArgAsExpr(0);
- llvm::APSInt NumParams(32);
- if (!NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
- << Attr.getName() << AANT_ArgumentIntegerConstant
- << NumParamsExpr->getSourceRange();
- return;
- }
-
- unsigned Num = NumParams.getLimitedValue(255);
- if ((Num & 1) || Num > 30) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
- << Attr.getName() << (int)NumParams.getSExtValue()
- << NumParamsExpr->getSourceRange();
- return;
- }
-
- d->addAttr(::new (S.Context) MSP430InterruptAttr(Attr.getLoc(), S.Context, Num));
- d->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context));
-}
-
-namespace {
- class MSP430AttributesSema : public TargetAttributesSema {
- public:
- MSP430AttributesSema() { }
- bool ProcessDeclAttribute(Scope *scope, Decl *D,
- const AttributeList &Attr, Sema &S) const {
- if (Attr.getKind() == AttributeList::AT_Interrupt) {
- HandleMSP430InterruptAttr(D, Attr, S);
- return true;
- }
- return false;
- }
- };
-}
-
-static void HandleX86ForceAlignArgPointerAttr(Decl *D,
- const AttributeList& Attr,
- Sema &S) {
- // If we try to apply it to a function pointer, don't warn, but don't
- // do anything, either. It doesn't matter anyway, because there's nothing
- // special about calling a force_align_arg_pointer function.
- ValueDecl *VD = dyn_cast<ValueDecl>(D);
- if (VD && VD->getType()->isFunctionPointerType())
- return;
- // Also don't warn on function pointer typedefs.
- TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D);
- if (TD && (TD->getUnderlyingType()->isFunctionPointerType() ||
- TD->getUnderlyingType()->isFunctionType()))
- return;
- // Attribute can only be applied to function types.
- if (!isa<FunctionDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << /* function */0;
- return;
- }
-
- D->addAttr(::new (S.Context) X86ForceAlignArgPointerAttr(Attr.getRange(),
- S.Context));
-}
-
-DLLImportAttr *Sema::mergeDLLImportAttr(Decl *D, SourceRange Range,
- unsigned AttrSpellingListIndex) {
- if (D->hasAttr<DLLExportAttr>()) {
- Diag(Range.getBegin(), diag::warn_attribute_ignored) << "dllimport";
- return NULL;
- }
-
- if (D->hasAttr<DLLImportAttr>())
- return NULL;
-
- if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
- if (VD->hasDefinition()) {
- // dllimport cannot be applied to definitions.
- Diag(D->getLocation(), diag::warn_attribute_invalid_on_definition)
- << "dllimport";
- return NULL;
- }
- }
-
- return ::new (Context) DLLImportAttr(Range, Context,
- AttrSpellingListIndex);
-}
-
-static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
- // Attribute can be applied only to functions or variables.
- FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
- if (!FD && !isa<VarDecl>(D)) {
- // Apparently Visual C++ thinks it is okay to not emit a warning
- // in this case, so only emit a warning when -fms-extensions is not
- // specified.
- if (!S.getLangOpts().MicrosoftExt)
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 2 /*variable and function*/;
- return;
- }
-
- // Currently, the dllimport attribute is ignored for inlined functions.
- // Warning is emitted.
- if (FD && FD->isInlineSpecified()) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
- return;
- }
-
- unsigned Index = Attr.getAttributeSpellingListIndex();
- DLLImportAttr *NewAttr = S.mergeDLLImportAttr(D, Attr.getRange(), Index);
- if (NewAttr)
- D->addAttr(NewAttr);
-}
-
-DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D, SourceRange Range,
- unsigned AttrSpellingListIndex) {
- if (DLLImportAttr *Import = D->getAttr<DLLImportAttr>()) {
- Diag(Import->getLocation(), diag::warn_attribute_ignored) << "dllimport";
- D->dropAttr<DLLImportAttr>();
- }
-
- if (D->hasAttr<DLLExportAttr>())
- return NULL;
-
- return ::new (Context) DLLExportAttr(Range, Context,
- AttrSpellingListIndex);
-}
-
-static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
- // Currently, the dllexport attribute is ignored for inlined functions, unless
- // the -fkeep-inline-functions flag has been used. Warning is emitted;
- if (isa<FunctionDecl>(D) && cast<FunctionDecl>(D)->isInlineSpecified()) {
- // FIXME: ... unless the -fkeep-inline-functions flag has been used.
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
- return;
- }
-
- unsigned Index = Attr.getAttributeSpellingListIndex();
- DLLExportAttr *NewAttr = S.mergeDLLExportAttr(D, Attr.getRange(), Index);
- if (NewAttr)
- D->addAttr(NewAttr);
-}
-
-namespace {
- class X86AttributesSema : public TargetAttributesSema {
- public:
- X86AttributesSema() { }
- bool ProcessDeclAttribute(Scope *scope, Decl *D,
- const AttributeList &Attr, Sema &S) const {
- const llvm::Triple &Triple(S.Context.getTargetInfo().getTriple());
- if (Triple.getOS() == llvm::Triple::Win32 ||
- Triple.getOS() == llvm::Triple::MinGW32) {
- switch (Attr.getKind()) {
- case AttributeList::AT_DLLImport: HandleDLLImportAttr(D, Attr, S);
- return true;
- case AttributeList::AT_DLLExport: HandleDLLExportAttr(D, Attr, S);
- return true;
- default: break;
- }
- }
- if (Triple.getArch() != llvm::Triple::x86_64 &&
- (Attr.getName()->getName() == "force_align_arg_pointer" ||
- Attr.getName()->getName() == "__force_align_arg_pointer__")) {
- HandleX86ForceAlignArgPointerAttr(D, Attr, S);
- return true;
- }
- return false;
- }
- };
-}
-
-namespace {
- class MipsAttributesSema : public TargetAttributesSema {
- public:
- MipsAttributesSema() { }
- bool ProcessDeclAttribute(Scope *scope, Decl *D, const AttributeList &Attr,
- Sema &S) const {
- if (Attr.getKind() == AttributeList::AT_Mips16) {
- D->addAttr(::new (S.Context) Mips16Attr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
- return true;
- } else if (Attr.getKind() == AttributeList::AT_NoMips16) {
- D->addAttr(::new (S.Context) NoMips16Attr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
- return true;
- }
- return false;
- }
- };
-}
-
-const TargetAttributesSema &Sema::getTargetAttributesSema() const {
- if (TheTargetAttributesSema)
- return *TheTargetAttributesSema;
-
- const llvm::Triple &Triple(Context.getTargetInfo().getTriple());
- switch (Triple.getArch()) {
- case llvm::Triple::arm:
- case llvm::Triple::thumb:
- return *(TheTargetAttributesSema = new ARMAttributesSema);
- case llvm::Triple::msp430:
- return *(TheTargetAttributesSema = new MSP430AttributesSema);
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- return *(TheTargetAttributesSema = new X86AttributesSema);
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- return *(TheTargetAttributesSema = new MipsAttributesSema);
- default:
- return *(TheTargetAttributesSema = new TargetAttributesSema);
- }
-}
Removed: cfe/trunk/lib/Sema/TargetAttributesSema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TargetAttributesSema.h?rev=198895&view=auto
==============================================================================
--- cfe/trunk/lib/Sema/TargetAttributesSema.h (original)
+++ cfe/trunk/lib/Sema/TargetAttributesSema.h (removed)
@@ -1,27 +0,0 @@
-//===--- TargetAttributesSema.h - Semantic Analysis For Target Attributes -===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef CLANG_SEMA_TARGETSEMA_H
-#define CLANG_SEMA_TARGETSEMA_H
-
-namespace clang {
- class Scope;
- class Decl;
- class AttributeList;
- class Sema;
-
- class TargetAttributesSema {
- public:
- virtual ~TargetAttributesSema();
- virtual bool ProcessDeclAttribute(Scope *scope, Decl *D,
- const AttributeList &Attr, Sema &S) const;
- };
-}
-
-#endif
Modified: cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?rev=198896&r1=198895&r2=198896&view=diff
==============================================================================
--- cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp (original)
+++ cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Thu Jan 9 16:48:32 2014
@@ -74,7 +74,8 @@ static StringRef NormalizeAttrSpelling(S
typedef std::vector<std::pair<std::string, Record *> > ParsedAttrMap;
-static ParsedAttrMap getParsedAttrList(const RecordKeeper &Records) {
+static ParsedAttrMap getParsedAttrList(const RecordKeeper &Records,
+ ParsedAttrMap *Dupes = 0) {
std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
std::set<std::string> Seen;
ParsedAttrMap R;
@@ -89,8 +90,11 @@ static ParsedAttrMap getParsedAttrList(c
// If this attribute has already been handled, it does not need to be
// handled again.
- if (Seen.find(AN) != Seen.end())
+ if (Seen.find(AN) != Seen.end()) {
+ if (Dupes)
+ Dupes->push_back(std::make_pair(AN, *I));
continue;
+ }
Seen.insert(AN);
} else
AN = NormalizeAttrName(Attr.getName()).str();
@@ -2063,15 +2067,111 @@ static std::string GenerateLangOptRequir
return FnName;
}
+static void GenerateDefaultTargetRequirements(raw_ostream &OS) {
+ OS << "static bool defaultTargetRequirements(llvm::Triple) {\n";
+ OS << " return true;\n";
+ OS << "}\n\n";
+}
+
+static std::string GenerateTargetRequirements(const Record &Attr,
+ const ParsedAttrMap &Dupes,
+ raw_ostream &OS) {
+ // If the attribute is not a target specific attribute, return the default
+ // target handler.
+ if (!Attr.isSubClassOf("TargetSpecificAttr"))
+ return "defaultTargetRequirements";
+
+ // Get the list of architectures to be tested for.
+ const Record *R = Attr.getValueAsDef("Target");
+ std::vector<std::string> Arches = R->getValueAsListOfStrings("Arches");
+ if (Arches.empty()) {
+ PrintError(Attr.getLoc(), "Empty list of target architectures for a "
+ "target-specific attr");
+ return "defaultTargetRequirements";
+ }
+
+ // If there are other attributes which share the same parsed attribute kind,
+ // such as target-specific attributes with a shared spelling, collapse the
+ // duplicate architectures. This is required because a shared target-specific
+ // attribute has only one AttributeList::Kind enumeration value, but it
+ // applies to multiple target architectures. In order for the attribute to be
+ // considered valid, all of its architectures need to be included.
+ if (!Attr.isValueUnset("ParseKind")) {
+ std::string APK = Attr.getValueAsString("ParseKind");
+ for (ParsedAttrMap::const_iterator I = Dupes.begin(), E = Dupes.end();
+ I != E; ++I) {
+ if (I->first == APK) {
+ std::vector<std::string> DA = I->second->getValueAsDef("Target")->
+ getValueAsListOfStrings("Arches");
+ std::copy(DA.begin(), DA.end(), std::back_inserter(Arches));
+ }
+ }
+ }
+
+ std::string FnName = "isTarget", Test = "(";
+ for (std::vector<std::string>::const_iterator I = Arches.begin(),
+ E = Arches.end(); I != E; ++I) {
+ std::string Part = *I;
+ Test += "Arch == llvm::Triple::" + Part;
+ if (I + 1 != E)
+ Test += " || ";
+ FnName += Part;
+ }
+ Test += ")";
+
+ // If the target also requires OS testing, generate those tests as well.
+ bool UsesOS = false;
+ if (!R->isValueUnset("OSes")) {
+ UsesOS = true;
+
+ // We know that there was at least one arch test, so we need to and in the
+ // OS tests.
+ Test += " && (";
+ std::vector<std::string> OSes = R->getValueAsListOfStrings("OSes");
+ for (std::vector<std::string>::const_iterator I = OSes.begin(),
+ E = OSes.end(); I != E; ++I) {
+ std::string Part = *I;
+
+ Test += "OS == llvm::Triple::" + 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;
+ std::set<std::string>::iterator I = CustomTargetSet.find(FnName);
+ if (I != CustomTargetSet.end())
+ return *I;
+
+ OS << "static bool " << FnName << "(llvm::Triple T) {\n";
+ OS << " llvm::Triple::ArchType Arch = T.getArch();\n";
+ if (UsesOS)
+ OS << " llvm::Triple::OSType OS = T.getOS();\n";
+ OS << " return " << Test << ";\n";
+ OS << "}\n\n";
+
+ CustomTargetSet.insert(FnName);
+ return FnName;
+}
+
/// Emits the parsed attribute helpers
void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
emitSourceFileHeader("Parsed attribute helpers", OS);
- ParsedAttrMap Attrs = getParsedAttrList(Records);
+ // Get the list of parsed attributes, and accept the optional list of
+ // duplicates due to the ParseKind.
+ ParsedAttrMap Dupes;
+ ParsedAttrMap Attrs = getParsedAttrList(Records, &Dupes);
- // Generate the default appertainsTo and language option diagnostic methods.
+ // Generate the default appertainsTo, target and language option diagnostic
+ // methods.
GenerateDefaultAppertainsTo(OS);
GenerateDefaultLangOptRequirements(OS);
+ GenerateDefaultTargetRequirements(OS);
// Generate the appertainsTo diagnostic methods and write their names into
// another mapping. At the same time, generate the AttrInfoMap object
@@ -2080,13 +2180,22 @@ void EmitClangAttrParsedAttrImpl(RecordK
std::stringstream SS;
for (ParsedAttrMap::iterator I = Attrs.begin(), E = Attrs.end(); I != E;
++I) {
+ // TODO: If the attribute's kind appears in the list of duplicates, that is
+ // because it is a target-specific attribute that appears multiple times.
+ // It would be beneficial to test whether the duplicates are "similar
+ // enough" to each other to not cause problems. For instance, check that
+ // the spellings are identicial, and custom parsing rules match, etc.
+
// We need to generate struct instances based off ParsedAttrInfo from
// AttributeList.cpp.
SS << " { ";
emitArgInfo(*I->second, SS);
SS << ", " << I->second->getValueAsBit("HasCustomParsing");
+ SS << ", " << I->second->isSubClassOf("TargetSpecificAttr");
+ SS << ", " << I->second->isSubClassOf("TypeAttr");
SS << ", " << GenerateAppertainsTo(*I->second, OS);
SS << ", " << GenerateLangOptRequirements(*I->second, OS);
+ SS << ", " << GenerateTargetRequirements(*I->second, Dupes, OS);
SS << " }";
if (I + 1 != E)
More information about the cfe-commits
mailing list