mirror of https://github.com/microsoft/clang.git
Automate attribute language option checking by specifying the list of options to test in tablegen.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@196138 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
c410ddbaca
commit
694680f7c4
|
@ -129,6 +129,13 @@ class SubjectList<list<AttrSubject> subjects, SubjectDiag diag = WarnDiag,
|
||||||
string CustomDiag = customDiag;
|
string CustomDiag = customDiag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class LangOpt<string name> {
|
||||||
|
string Name = name;
|
||||||
|
}
|
||||||
|
def MicrosoftExt : LangOpt<"MicrosoftExt">;
|
||||||
|
def Borland : LangOpt<"Borland">;
|
||||||
|
def CUDA : LangOpt<"CUDA">;
|
||||||
|
|
||||||
class Attr {
|
class Attr {
|
||||||
// The various ways in which an attribute can be spelled in source
|
// The various ways in which an attribute can be spelled in source
|
||||||
list<Spelling> Spellings;
|
list<Spelling> Spellings;
|
||||||
|
@ -155,6 +162,9 @@ class Attr {
|
||||||
// content. Eg) It parses 3 args, but semantically takes 4 args. Opts out of
|
// content. Eg) It parses 3 args, but semantically takes 4 args. Opts out of
|
||||||
// common attribute error checking.
|
// common attribute error checking.
|
||||||
bit HasCustomParsing = 0;
|
bit HasCustomParsing = 0;
|
||||||
|
// Lists language options, one of which is required to be true for the
|
||||||
|
// attribute to be applicable. If empty, no language options are required.
|
||||||
|
list<LangOpt> LangOpts = [];
|
||||||
// Any additional text that should be included verbatim in the class.
|
// Any additional text that should be included verbatim in the class.
|
||||||
code AdditionalMembers = [{}];
|
code AdditionalMembers = [{}];
|
||||||
}
|
}
|
||||||
|
@ -352,31 +362,37 @@ def Constructor : InheritableAttr {
|
||||||
def CUDAConstant : InheritableAttr {
|
def CUDAConstant : InheritableAttr {
|
||||||
let Spellings = [GNU<"constant">];
|
let Spellings = [GNU<"constant">];
|
||||||
let Subjects = SubjectList<[Var]>;
|
let Subjects = SubjectList<[Var]>;
|
||||||
|
let LangOpts = [CUDA];
|
||||||
}
|
}
|
||||||
|
|
||||||
def CUDADevice : InheritableAttr {
|
def CUDADevice : InheritableAttr {
|
||||||
let Spellings = [GNU<"device">];
|
let Spellings = [GNU<"device">];
|
||||||
let Subjects = SubjectList<[Function, Var]>;
|
let Subjects = SubjectList<[Function, Var]>;
|
||||||
|
let LangOpts = [CUDA];
|
||||||
}
|
}
|
||||||
|
|
||||||
def CUDAGlobal : InheritableAttr {
|
def CUDAGlobal : InheritableAttr {
|
||||||
let Spellings = [GNU<"global">];
|
let Spellings = [GNU<"global">];
|
||||||
let Subjects = SubjectList<[Function]>;
|
let Subjects = SubjectList<[Function]>;
|
||||||
|
let LangOpts = [CUDA];
|
||||||
}
|
}
|
||||||
|
|
||||||
def CUDAHost : InheritableAttr {
|
def CUDAHost : InheritableAttr {
|
||||||
let Spellings = [GNU<"host">];
|
let Spellings = [GNU<"host">];
|
||||||
let Subjects = SubjectList<[Function]>;
|
let Subjects = SubjectList<[Function]>;
|
||||||
|
let LangOpts = [CUDA];
|
||||||
}
|
}
|
||||||
|
|
||||||
def CUDALaunchBounds : InheritableAttr {
|
def CUDALaunchBounds : InheritableAttr {
|
||||||
let Spellings = [GNU<"launch_bounds">];
|
let Spellings = [GNU<"launch_bounds">];
|
||||||
let Args = [IntArgument<"MaxThreads">, DefaultIntArgument<"MinBlocks", 0>];
|
let Args = [IntArgument<"MaxThreads">, DefaultIntArgument<"MinBlocks", 0>];
|
||||||
|
let LangOpts = [CUDA];
|
||||||
}
|
}
|
||||||
|
|
||||||
def CUDAShared : InheritableAttr {
|
def CUDAShared : InheritableAttr {
|
||||||
let Spellings = [GNU<"shared">];
|
let Spellings = [GNU<"shared">];
|
||||||
let Subjects = SubjectList<[Var]>;
|
let Subjects = SubjectList<[Var]>;
|
||||||
|
let LangOpts = [CUDA];
|
||||||
}
|
}
|
||||||
|
|
||||||
def C11NoReturn : InheritableAttr {
|
def C11NoReturn : InheritableAttr {
|
||||||
|
@ -823,6 +839,7 @@ def Uuid : InheritableAttr {
|
||||||
let Spellings = [GNU<"uuid">];
|
let Spellings = [GNU<"uuid">];
|
||||||
let Args = [StringArgument<"Guid">];
|
let Args = [StringArgument<"Guid">];
|
||||||
// let Subjects = SubjectList<[CXXRecord]>;
|
// let Subjects = SubjectList<[CXXRecord]>;
|
||||||
|
let LangOpts = [MicrosoftExt, Borland];
|
||||||
}
|
}
|
||||||
|
|
||||||
def VectorSize : TypeAttr {
|
def VectorSize : TypeAttr {
|
||||||
|
@ -1159,14 +1176,17 @@ def DLLImport : InheritableAttr, TargetSpecificAttr {
|
||||||
|
|
||||||
def ForceInline : InheritableAttr {
|
def ForceInline : InheritableAttr {
|
||||||
let Spellings = [Keyword<"__forceinline">];
|
let Spellings = [Keyword<"__forceinline">];
|
||||||
|
let LangOpts = [MicrosoftExt];
|
||||||
}
|
}
|
||||||
|
|
||||||
def SelectAny : InheritableAttr {
|
def SelectAny : InheritableAttr {
|
||||||
let Spellings = [Declspec<"selectany">];
|
let Spellings = [Declspec<"selectany">];
|
||||||
|
let LangOpts = [MicrosoftExt];
|
||||||
}
|
}
|
||||||
|
|
||||||
def Win64 : InheritableAttr {
|
def Win64 : InheritableAttr {
|
||||||
let Spellings = [Keyword<"__w64">];
|
let Spellings = [Keyword<"__w64">];
|
||||||
|
let LangOpts = [MicrosoftExt];
|
||||||
}
|
}
|
||||||
|
|
||||||
def Ptr32 : TypeAttr {
|
def Ptr32 : TypeAttr {
|
||||||
|
@ -1185,7 +1205,9 @@ def UPtr : TypeAttr {
|
||||||
let Spellings = [Keyword<"__uptr">];
|
let Spellings = [Keyword<"__uptr">];
|
||||||
}
|
}
|
||||||
|
|
||||||
class MSInheritanceAttr : InheritableAttr;
|
class MSInheritanceAttr : InheritableAttr {
|
||||||
|
let LangOpts = [MicrosoftExt];
|
||||||
|
}
|
||||||
|
|
||||||
def SingleInheritance : MSInheritanceAttr {
|
def SingleInheritance : MSInheritanceAttr {
|
||||||
let Spellings = [Keyword<"__single_inheritance">];
|
let Spellings = [Keyword<"__single_inheritance">];
|
||||||
|
|
|
@ -468,6 +468,7 @@ public:
|
||||||
unsigned getMinArgs() const;
|
unsigned getMinArgs() const;
|
||||||
unsigned getMaxArgs() const;
|
unsigned getMaxArgs() const;
|
||||||
bool diagnoseAppertainsTo(class Sema &S, const Decl *D) const;
|
bool diagnoseAppertainsTo(class Sema &S, const Decl *D) const;
|
||||||
|
bool diagnoseLangOpts(class Sema &S) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A factory, from which one makes pools, from which one creates
|
/// A factory, from which one makes pools, from which one creates
|
||||||
|
|
|
@ -155,6 +155,7 @@ struct ParsedAttrInfo {
|
||||||
|
|
||||||
bool (*DiagAppertainsToDecl)(Sema &S, const AttributeList &Attr,
|
bool (*DiagAppertainsToDecl)(Sema &S, const AttributeList &Attr,
|
||||||
const Decl *);
|
const Decl *);
|
||||||
|
bool (*DiagLangOpts)(Sema &S, const AttributeList &Attr);
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -180,3 +181,7 @@ bool AttributeList::hasCustomParsing() const {
|
||||||
bool AttributeList::diagnoseAppertainsTo(Sema &S, const Decl *D) const {
|
bool AttributeList::diagnoseAppertainsTo(Sema &S, const Decl *D) const {
|
||||||
return getInfo(*this).DiagAppertainsToDecl(S, *this, D);
|
return getInfo(*this).DiagAppertainsToDecl(S, *this, D);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AttributeList::diagnoseLangOpts(Sema &S) const {
|
||||||
|
return getInfo(*this).DiagLangOpts(S, *this);
|
||||||
|
}
|
||||||
|
|
|
@ -3143,18 +3143,7 @@ static void handleNoDebugAttr(Sema &S, Decl *D, const AttributeList &Attr) {
|
||||||
Attr.getAttributeSpellingListIndex()));
|
Attr.getAttributeSpellingListIndex()));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handleConstantAttr(Sema &S, Decl *D, const AttributeList &Attr) {
|
|
||||||
if (S.LangOpts.CUDA) {
|
|
||||||
D->addAttr(::new (S.Context)
|
|
||||||
CUDAConstantAttr(Attr.getRange(), S.Context,
|
|
||||||
Attr.getAttributeSpellingListIndex()));
|
|
||||||
} else {
|
|
||||||
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handleDeviceAttr(Sema &S, Decl *D, const AttributeList &Attr) {
|
static void handleDeviceAttr(Sema &S, Decl *D, const AttributeList &Attr) {
|
||||||
if (S.LangOpts.CUDA) {
|
|
||||||
// check the attribute arguments.
|
// check the attribute arguments.
|
||||||
if (Attr.getNumArgs() != 0) {
|
if (Attr.getNumArgs() != 0) {
|
||||||
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
|
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
|
||||||
|
@ -3165,13 +3154,9 @@ static void handleDeviceAttr(Sema &S, Decl *D, const AttributeList &Attr) {
|
||||||
D->addAttr(::new (S.Context)
|
D->addAttr(::new (S.Context)
|
||||||
CUDADeviceAttr(Attr.getRange(), S.Context,
|
CUDADeviceAttr(Attr.getRange(), S.Context,
|
||||||
Attr.getAttributeSpellingListIndex()));
|
Attr.getAttributeSpellingListIndex()));
|
||||||
} else {
|
|
||||||
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) {
|
static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) {
|
||||||
if (S.LangOpts.CUDA) {
|
|
||||||
FunctionDecl *FD = cast<FunctionDecl>(D);
|
FunctionDecl *FD = cast<FunctionDecl>(D);
|
||||||
if (!FD->getResultType()->isVoidType()) {
|
if (!FD->getResultType()->isVoidType()) {
|
||||||
TypeLoc TL = FD->getTypeSourceInfo()->getTypeLoc().IgnoreParens();
|
TypeLoc TL = FD->getTypeSourceInfo()->getTypeLoc().IgnoreParens();
|
||||||
|
@ -3190,29 +3175,6 @@ static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) {
|
||||||
D->addAttr(::new (S.Context)
|
D->addAttr(::new (S.Context)
|
||||||
CUDAGlobalAttr(Attr.getRange(), S.Context,
|
CUDAGlobalAttr(Attr.getRange(), S.Context,
|
||||||
Attr.getAttributeSpellingListIndex()));
|
Attr.getAttributeSpellingListIndex()));
|
||||||
} else {
|
|
||||||
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handleHostAttr(Sema &S, Decl *D, const AttributeList &Attr) {
|
|
||||||
if (S.LangOpts.CUDA) {
|
|
||||||
D->addAttr(::new (S.Context)
|
|
||||||
CUDAHostAttr(Attr.getRange(), S.Context,
|
|
||||||
Attr.getAttributeSpellingListIndex()));
|
|
||||||
} else {
|
|
||||||
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handleSharedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
|
|
||||||
if (S.LangOpts.CUDA) {
|
|
||||||
D->addAttr(::new (S.Context)
|
|
||||||
CUDASharedAttr(Attr.getRange(), S.Context,
|
|
||||||
Attr.getAttributeSpellingListIndex()));
|
|
||||||
} else {
|
|
||||||
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handleGNUInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) {
|
static void handleGNUInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) {
|
||||||
|
@ -3443,7 +3405,6 @@ bool Sema::CheckRegparmAttr(const AttributeList &Attr, unsigned &numParams) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handleLaunchBoundsAttr(Sema &S, Decl *D, const AttributeList &Attr){
|
static void handleLaunchBoundsAttr(Sema &S, Decl *D, const AttributeList &Attr){
|
||||||
if (S.LangOpts.CUDA) {
|
|
||||||
// check the attribute arguments.
|
// check the attribute arguments.
|
||||||
if (Attr.getNumArgs() != 1 && Attr.getNumArgs() != 2) {
|
if (Attr.getNumArgs() != 1 && Attr.getNumArgs() != 2) {
|
||||||
// FIXME: 0 is not okay.
|
// FIXME: 0 is not okay.
|
||||||
|
@ -3466,9 +3427,6 @@ static void handleLaunchBoundsAttr(Sema &S, Decl *D, const AttributeList &Attr){
|
||||||
CUDALaunchBoundsAttr(Attr.getRange(), S.Context,
|
CUDALaunchBoundsAttr(Attr.getRange(), S.Context,
|
||||||
MaxThreads, MinBlocks,
|
MaxThreads, MinBlocks,
|
||||||
Attr.getAttributeSpellingListIndex()));
|
Attr.getAttributeSpellingListIndex()));
|
||||||
} else {
|
|
||||||
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "launch_bounds";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D,
|
static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D,
|
||||||
|
@ -3847,16 +3805,6 @@ static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D,
|
||||||
// Microsoft specific attribute handlers.
|
// Microsoft specific attribute handlers.
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
// Check if MS extensions or some other language extensions are enabled. If
|
|
||||||
// not, issue a diagnostic that the given attribute is unused.
|
|
||||||
static bool checkMicrosoftExt(Sema &S, const AttributeList &Attr,
|
|
||||||
bool OtherExtension = false) {
|
|
||||||
if (S.LangOpts.MicrosoftExt || OtherExtension)
|
|
||||||
return true;
|
|
||||||
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) {
|
static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) {
|
||||||
if (!S.LangOpts.CPlusPlus) {
|
if (!S.LangOpts.CPlusPlus) {
|
||||||
S.Diag(Attr.getLoc(), diag::err_attribute_not_supported_in_lang)
|
S.Diag(Attr.getLoc(), diag::err_attribute_not_supported_in_lang)
|
||||||
|
@ -3864,9 +3812,6 @@ static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!checkMicrosoftExt(S, Attr, S.LangOpts.Borland))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!isa<CXXRecordDecl>(D)) {
|
if (!isa<CXXRecordDecl>(D)) {
|
||||||
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
|
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
|
||||||
<< Attr.getName() << ExpectedClass;
|
<< Attr.getName() << ExpectedClass;
|
||||||
|
@ -3905,54 +3850,6 @@ static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) {
|
||||||
Attr.getAttributeSpellingListIndex()));
|
Attr.getAttributeSpellingListIndex()));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handleInheritanceAttr(Sema &S, Decl *D, const AttributeList &Attr) {
|
|
||||||
if (!checkMicrosoftExt(S, Attr))
|
|
||||||
return;
|
|
||||||
|
|
||||||
AttributeList::Kind Kind = Attr.getKind();
|
|
||||||
if (Kind == AttributeList::AT_SingleInheritance)
|
|
||||||
D->addAttr(
|
|
||||||
::new (S.Context)
|
|
||||||
SingleInheritanceAttr(Attr.getRange(), S.Context,
|
|
||||||
Attr.getAttributeSpellingListIndex()));
|
|
||||||
else if (Kind == AttributeList::AT_MultipleInheritance)
|
|
||||||
D->addAttr(
|
|
||||||
::new (S.Context)
|
|
||||||
MultipleInheritanceAttr(Attr.getRange(), S.Context,
|
|
||||||
Attr.getAttributeSpellingListIndex()));
|
|
||||||
else if (Kind == AttributeList::AT_VirtualInheritance)
|
|
||||||
D->addAttr(
|
|
||||||
::new (S.Context)
|
|
||||||
VirtualInheritanceAttr(Attr.getRange(), S.Context,
|
|
||||||
Attr.getAttributeSpellingListIndex()));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handleWin64Attr(Sema &S, Decl *D, const AttributeList &Attr) {
|
|
||||||
if (!checkMicrosoftExt(S, Attr))
|
|
||||||
return;
|
|
||||||
|
|
||||||
D->addAttr(::new (S.Context) Win64Attr(Attr.getRange(), S.Context,
|
|
||||||
Attr.getAttributeSpellingListIndex()));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handleForceInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) {
|
|
||||||
if (!checkMicrosoftExt(S, Attr))
|
|
||||||
return;
|
|
||||||
D->addAttr(::new (S.Context)
|
|
||||||
ForceInlineAttr(Attr.getRange(), S.Context,
|
|
||||||
Attr.getAttributeSpellingListIndex()));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handleSelectAnyAttr(Sema &S, Decl *D, const AttributeList &Attr) {
|
|
||||||
if (!checkMicrosoftExt(S, Attr))
|
|
||||||
return;
|
|
||||||
// Check linkage after possibly merging declaratinos. See
|
|
||||||
// checkAttributesAfterMerging().
|
|
||||||
D->addAttr(::new (S.Context)
|
|
||||||
SelectAnyAttr(Attr.getRange(), S.Context,
|
|
||||||
Attr.getAttributeSpellingListIndex()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Handles semantic checking for features that are common to all attributes,
|
/// Handles semantic checking for features that are common to all attributes,
|
||||||
/// such as checking whether a parameter was properly specified, or the correct
|
/// such as checking whether a parameter was properly specified, or the correct
|
||||||
/// number of arguments were passed, etc.
|
/// number of arguments were passed, etc.
|
||||||
|
@ -3968,6 +3865,11 @@ static bool handleCommonAttributeFeatures(Sema &S, Scope *scope, Decl *D,
|
||||||
Attr.getKind() == AttributeList::IgnoredAttribute)
|
Attr.getKind() == AttributeList::IgnoredAttribute)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// Check whether the attribute requires specific language extensions to be
|
||||||
|
// enabled.
|
||||||
|
if (!Attr.diagnoseLangOpts(S))
|
||||||
|
return true;
|
||||||
|
|
||||||
// If there are no optional arguments, then checking for the argument count
|
// If there are no optional arguments, then checking for the argument count
|
||||||
// is trivial.
|
// is trivial.
|
||||||
if (Attr.getMinArgs() == Attr.getMaxArgs() &&
|
if (Attr.getMinArgs() == Attr.getMaxArgs() &&
|
||||||
|
@ -4034,7 +3936,8 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
|
||||||
handleDependencyAttr(S, scope, D, Attr);
|
handleDependencyAttr(S, scope, D, Attr);
|
||||||
break;
|
break;
|
||||||
case AttributeList::AT_Common: handleCommonAttr (S, D, Attr); break;
|
case AttributeList::AT_Common: handleCommonAttr (S, D, Attr); break;
|
||||||
case AttributeList::AT_CUDAConstant:handleConstantAttr (S, D, Attr); break;
|
case AttributeList::AT_CUDAConstant:
|
||||||
|
handleSimpleAttribute<CUDAConstantAttr>(S, D, Attr); break;
|
||||||
case AttributeList::AT_Constructor: handleConstructorAttr (S, D, Attr); break;
|
case AttributeList::AT_Constructor: handleConstructorAttr (S, D, Attr); break;
|
||||||
case AttributeList::AT_CXX11NoReturn:
|
case AttributeList::AT_CXX11NoReturn:
|
||||||
handleSimpleAttribute<CXX11NoReturnAttr>(S, D, Attr); break;
|
handleSimpleAttribute<CXX11NoReturnAttr>(S, D, Attr); break;
|
||||||
|
@ -4052,7 +3955,8 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
|
||||||
case AttributeList::AT_FormatArg: handleFormatArgAttr (S, D, Attr); break;
|
case AttributeList::AT_FormatArg: handleFormatArgAttr (S, D, Attr); break;
|
||||||
case AttributeList::AT_CUDAGlobal: handleGlobalAttr (S, D, Attr); break;
|
case AttributeList::AT_CUDAGlobal: handleGlobalAttr (S, D, Attr); break;
|
||||||
case AttributeList::AT_CUDADevice: handleDeviceAttr (S, D, Attr); break;
|
case AttributeList::AT_CUDADevice: handleDeviceAttr (S, D, Attr); break;
|
||||||
case AttributeList::AT_CUDAHost: handleHostAttr (S, D, Attr); break;
|
case AttributeList::AT_CUDAHost:
|
||||||
|
handleSimpleAttribute<CUDAHostAttr>(S, D, Attr); break;
|
||||||
case AttributeList::AT_GNUInline: handleGNUInlineAttr (S, D, Attr); break;
|
case AttributeList::AT_GNUInline: handleGNUInlineAttr (S, D, Attr); break;
|
||||||
case AttributeList::AT_CUDALaunchBounds:
|
case AttributeList::AT_CUDALaunchBounds:
|
||||||
handleLaunchBoundsAttr(S, D, Attr);
|
handleLaunchBoundsAttr(S, D, Attr);
|
||||||
|
@ -4073,7 +3977,8 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
|
||||||
handleSimpleAttribute<NakedAttr>(S, D, Attr); break;
|
handleSimpleAttribute<NakedAttr>(S, D, Attr); break;
|
||||||
case AttributeList::AT_NoReturn: handleNoReturnAttr (S, D, Attr); break;
|
case AttributeList::AT_NoReturn: handleNoReturnAttr (S, D, Attr); break;
|
||||||
case AttributeList::AT_NoThrow: handleNothrowAttr (S, D, Attr); break;
|
case AttributeList::AT_NoThrow: handleNothrowAttr (S, D, Attr); break;
|
||||||
case AttributeList::AT_CUDAShared: handleSharedAttr (S, D, Attr); break;
|
case AttributeList::AT_CUDAShared:
|
||||||
|
handleSimpleAttribute<CUDASharedAttr>(S, D, Attr); break;
|
||||||
case AttributeList::AT_VecReturn: handleVecReturnAttr (S, D, Attr); break;
|
case AttributeList::AT_VecReturn: handleVecReturnAttr (S, D, Attr); break;
|
||||||
|
|
||||||
case AttributeList::AT_ObjCOwnership:
|
case AttributeList::AT_ObjCOwnership:
|
||||||
|
@ -4206,18 +4111,17 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
|
||||||
handleUuidAttr(S, D, Attr);
|
handleUuidAttr(S, D, Attr);
|
||||||
break;
|
break;
|
||||||
case AttributeList::AT_SingleInheritance:
|
case AttributeList::AT_SingleInheritance:
|
||||||
|
handleSimpleAttribute<SingleInheritanceAttr>(S, D, Attr); break;
|
||||||
case AttributeList::AT_MultipleInheritance:
|
case AttributeList::AT_MultipleInheritance:
|
||||||
|
handleSimpleAttribute<MultipleInheritanceAttr>(S, D, Attr); break;
|
||||||
case AttributeList::AT_VirtualInheritance:
|
case AttributeList::AT_VirtualInheritance:
|
||||||
handleInheritanceAttr(S, D, Attr);
|
handleSimpleAttribute<VirtualInheritanceAttr>(S, D, Attr); break;
|
||||||
break;
|
|
||||||
case AttributeList::AT_Win64:
|
case AttributeList::AT_Win64:
|
||||||
handleWin64Attr(S, D, Attr); break;
|
handleSimpleAttribute<Win64Attr>(S, D, Attr); break;
|
||||||
case AttributeList::AT_ForceInline:
|
case AttributeList::AT_ForceInline:
|
||||||
handleForceInlineAttr(S, D, Attr);
|
handleSimpleAttribute<ForceInlineAttr>(S, D, Attr); break;
|
||||||
break;
|
|
||||||
case AttributeList::AT_SelectAny:
|
case AttributeList::AT_SelectAny:
|
||||||
handleSelectAnyAttr(S, D, Attr);
|
handleSimpleAttribute<SelectAnyAttr>(S, D, Attr); break;
|
||||||
break;
|
|
||||||
|
|
||||||
// Thread safety attributes:
|
// Thread safety attributes:
|
||||||
case AttributeList::AT_AssertExclusiveLock:
|
case AttributeList::AT_AssertExclusiveLock:
|
||||||
|
|
|
@ -1900,14 +1900,64 @@ static std::string GenerateAppertainsTo(const Record &Attr, raw_ostream &OS) {
|
||||||
return FnName;
|
return FnName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void GenerateDefaultLangOptRequirements(raw_ostream &OS) {
|
||||||
|
OS << "static bool defaultDiagnoseLangOpts(Sema &, ";
|
||||||
|
OS << "const AttributeList &) {\n";
|
||||||
|
OS << " return true;\n";
|
||||||
|
OS << "}\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string GenerateLangOptRequirements(const Record &R,
|
||||||
|
raw_ostream &OS) {
|
||||||
|
// If the attribute has an empty or unset list of language requirements,
|
||||||
|
// return the default handler.
|
||||||
|
std::vector<Record *> LangOpts = R.getValueAsListOfDefs("LangOpts");
|
||||||
|
if (LangOpts.empty())
|
||||||
|
return "defaultDiagnoseLangOpts";
|
||||||
|
|
||||||
|
// Generate the test condition, as well as a unique function name for the
|
||||||
|
// diagnostic test. The list of options should usually be short (one or two
|
||||||
|
// options), and the uniqueness isn't strictly necessary (it is just for
|
||||||
|
// codegen efficiency).
|
||||||
|
std::string FnName = "check", Test;
|
||||||
|
for (std::vector<Record *>::const_iterator I = LangOpts.begin(),
|
||||||
|
E = LangOpts.end(); I != E; ++I) {
|
||||||
|
std::string Part = (*I)->getValueAsString("Name");
|
||||||
|
Test += "S.LangOpts." + Part;
|
||||||
|
if (I + 1 != E)
|
||||||
|
Test += " || ";
|
||||||
|
FnName += Part;
|
||||||
|
}
|
||||||
|
FnName += "LangOpts";
|
||||||
|
|
||||||
|
// If this code has already been generated, simply return the previous
|
||||||
|
// instance of it.
|
||||||
|
static std::set<std::string> CustomLangOptsSet;
|
||||||
|
std::set<std::string>::iterator I = CustomLangOptsSet.find(FnName);
|
||||||
|
if (I != CustomLangOptsSet.end())
|
||||||
|
return *I;
|
||||||
|
|
||||||
|
OS << "static bool " << FnName << "(Sema &S, const AttributeList &Attr) {\n";
|
||||||
|
OS << " if (" << Test << ")\n";
|
||||||
|
OS << " return true;\n\n";
|
||||||
|
OS << " S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) ";
|
||||||
|
OS << "<< Attr.getName();\n";
|
||||||
|
OS << " return false;\n";
|
||||||
|
OS << "}\n\n";
|
||||||
|
|
||||||
|
CustomLangOptsSet.insert(FnName);
|
||||||
|
return FnName;
|
||||||
|
}
|
||||||
|
|
||||||
/// Emits the parsed attribute helpers
|
/// Emits the parsed attribute helpers
|
||||||
void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
|
void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
|
||||||
emitSourceFileHeader("Parsed attribute helpers", OS);
|
emitSourceFileHeader("Parsed attribute helpers", OS);
|
||||||
|
|
||||||
ParsedAttrMap Attrs = getParsedAttrList(Records);
|
ParsedAttrMap Attrs = getParsedAttrList(Records);
|
||||||
|
|
||||||
// Generate the default appertainsTo diagnostic method.
|
// Generate the default appertainsTo and language option diagnostic methods.
|
||||||
GenerateDefaultAppertainsTo(OS);
|
GenerateDefaultAppertainsTo(OS);
|
||||||
|
GenerateDefaultLangOptRequirements(OS);
|
||||||
|
|
||||||
// Generate the appertainsTo diagnostic methods and write their names into
|
// Generate the appertainsTo diagnostic methods and write their names into
|
||||||
// another mapping. At the same time, generate the AttrInfoMap object
|
// another mapping. At the same time, generate the AttrInfoMap object
|
||||||
|
@ -1922,6 +1972,7 @@ void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
|
||||||
emitArgInfo(*I->second, SS);
|
emitArgInfo(*I->second, SS);
|
||||||
SS << ", " << I->second->getValueAsBit("HasCustomParsing");
|
SS << ", " << I->second->getValueAsBit("HasCustomParsing");
|
||||||
SS << ", " << GenerateAppertainsTo(*I->second, OS);
|
SS << ", " << GenerateAppertainsTo(*I->second, OS);
|
||||||
|
SS << ", " << GenerateLangOptRequirements(*I->second, OS);
|
||||||
SS << " }";
|
SS << " }";
|
||||||
|
|
||||||
if (I + 1 != E)
|
if (I + 1 != E)
|
||||||
|
|
Loading…
Reference in New Issue