string CustomDiag = customDiag;
}
+class LangOpt<string name> {
+ string Name = name;
+}
+def MicrosoftExt : LangOpt<"MicrosoftExt">;
+def Borland : LangOpt<"Borland">;
+def CUDA : LangOpt<"CUDA">;
+
class Attr {
// The various ways in which an attribute can be spelled in source
list<Spelling> Spellings;
// content. Eg) It parses 3 args, but semantically takes 4 args. Opts out of
// common attribute error checking.
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.
code AdditionalMembers = [{}];
}
def CUDAConstant : InheritableAttr {
let Spellings = [GNU<"constant">];
let Subjects = SubjectList<[Var]>;
+ let LangOpts = [CUDA];
}
def CUDADevice : InheritableAttr {
let Spellings = [GNU<"device">];
let Subjects = SubjectList<[Function, Var]>;
+ let LangOpts = [CUDA];
}
def CUDAGlobal : InheritableAttr {
let Spellings = [GNU<"global">];
let Subjects = SubjectList<[Function]>;
+ let LangOpts = [CUDA];
}
def CUDAHost : InheritableAttr {
let Spellings = [GNU<"host">];
let Subjects = SubjectList<[Function]>;
+ let LangOpts = [CUDA];
}
def CUDALaunchBounds : InheritableAttr {
let Spellings = [GNU<"launch_bounds">];
let Args = [IntArgument<"MaxThreads">, DefaultIntArgument<"MinBlocks", 0>];
+ let LangOpts = [CUDA];
}
def CUDAShared : InheritableAttr {
let Spellings = [GNU<"shared">];
let Subjects = SubjectList<[Var]>;
+ let LangOpts = [CUDA];
}
def C11NoReturn : InheritableAttr {
let Spellings = [GNU<"uuid">];
let Args = [StringArgument<"Guid">];
// let Subjects = SubjectList<[CXXRecord]>;
+ let LangOpts = [MicrosoftExt, Borland];
}
def VectorSize : TypeAttr {
def ForceInline : InheritableAttr {
let Spellings = [Keyword<"__forceinline">];
+ let LangOpts = [MicrosoftExt];
}
def SelectAny : InheritableAttr {
let Spellings = [Declspec<"selectany">];
+ let LangOpts = [MicrosoftExt];
}
def Win64 : InheritableAttr {
let Spellings = [Keyword<"__w64">];
+ let LangOpts = [MicrosoftExt];
}
def Ptr32 : TypeAttr {
let Spellings = [Keyword<"__uptr">];
}
-class MSInheritanceAttr : InheritableAttr;
+class MSInheritanceAttr : InheritableAttr {
+ let LangOpts = [MicrosoftExt];
+}
def SingleInheritance : MSInheritanceAttr {
let Spellings = [Keyword<"__single_inheritance">];
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) {
- if (S.LangOpts.CUDA) {
- // check the attribute arguments.
- if (Attr.getNumArgs() != 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << Attr.getName() << 0;
- return;
- }
-
- D->addAttr(::new (S.Context)
- CUDADeviceAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
- } else {
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+ // check the attribute arguments.
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << Attr.getName() << 0;
+ return;
}
+
+ D->addAttr(::new (S.Context)
+ CUDADeviceAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (S.LangOpts.CUDA) {
- FunctionDecl *FD = cast<FunctionDecl>(D);
- if (!FD->getResultType()->isVoidType()) {
- TypeLoc TL = FD->getTypeSourceInfo()->getTypeLoc().IgnoreParens();
- if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) {
- S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return)
- << FD->getType()
- << FixItHint::CreateReplacement(FTL.getResultLoc().getSourceRange(),
- "void");
- } else {
- S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return)
- << FD->getType();
- }
- return;
+ FunctionDecl *FD = cast<FunctionDecl>(D);
+ if (!FD->getResultType()->isVoidType()) {
+ TypeLoc TL = FD->getTypeSourceInfo()->getTypeLoc().IgnoreParens();
+ if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) {
+ S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return)
+ << FD->getType()
+ << FixItHint::CreateReplacement(FTL.getResultLoc().getSourceRange(),
+ "void");
+ } else {
+ S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return)
+ << FD->getType();
}
-
- D->addAttr(::new (S.Context)
- CUDAGlobalAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
- } else {
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+ return;
}
-}
-static void handleHostAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (S.LangOpts.CUDA) {
- D->addAttr(::new (S.Context)
- CUDAHostAttr(Attr.getRange(), S.Context,
+ D->addAttr(::new (S.Context)
+ CUDAGlobalAttr(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 handleLaunchBoundsAttr(Sema &S, Decl *D, const AttributeList &Attr){
- if (S.LangOpts.CUDA) {
- // check the attribute arguments.
- if (Attr.getNumArgs() != 1 && Attr.getNumArgs() != 2) {
- // FIXME: 0 is not okay.
- S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 2;
- return;
- }
+ // check the attribute arguments.
+ if (Attr.getNumArgs() != 1 && Attr.getNumArgs() != 2) {
+ // FIXME: 0 is not okay.
+ S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 2;
+ return;
+ }
- if (!isFunctionOrMethod(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunctionOrMethod;
- return;
- }
+ if (!isFunctionOrMethod(D)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << ExpectedFunctionOrMethod;
+ return;
+ }
- uint32_t MaxThreads, MinBlocks;
- if (!checkUInt32Argument(S, Attr, Attr.getArgAsExpr(0), MaxThreads, 1) ||
- !checkUInt32Argument(S, Attr, Attr.getArgAsExpr(1), MinBlocks, 2))
- return;
+ uint32_t MaxThreads, MinBlocks;
+ if (!checkUInt32Argument(S, Attr, Attr.getArgAsExpr(0), MaxThreads, 1) ||
+ !checkUInt32Argument(S, Attr, Attr.getArgAsExpr(1), MinBlocks, 2))
+ return;
- D->addAttr(::new (S.Context)
- CUDALaunchBoundsAttr(Attr.getRange(), S.Context,
- MaxThreads, MinBlocks,
- Attr.getAttributeSpellingListIndex()));
- } else {
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "launch_bounds";
- }
+ D->addAttr(::new (S.Context)
+ CUDALaunchBoundsAttr(Attr.getRange(), S.Context,
+ MaxThreads, MinBlocks,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D,
// 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) {
if (!S.LangOpts.CPlusPlus) {
S.Diag(Attr.getLoc(), diag::err_attribute_not_supported_in_lang)
return;
}
- if (!checkMicrosoftExt(S, Attr, S.LangOpts.Borland))
- return;
-
if (!isa<CXXRecordDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedClass;
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,
/// such as checking whether a parameter was properly specified, or the correct
/// number of arguments were passed, etc.
Attr.getKind() == AttributeList::IgnoredAttribute)
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
// is trivial.
if (Attr.getMinArgs() == Attr.getMaxArgs() &&
handleDependencyAttr(S, scope, 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_CXX11NoReturn:
handleSimpleAttribute<CXX11NoReturnAttr>(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_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_CUDALaunchBounds:
handleLaunchBoundsAttr(S, D, Attr);
handleSimpleAttribute<NakedAttr>(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_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_ObjCOwnership:
handleUuidAttr(S, D, Attr);
break;
case AttributeList::AT_SingleInheritance:
+ handleSimpleAttribute<SingleInheritanceAttr>(S, D, Attr); break;
case AttributeList::AT_MultipleInheritance:
+ handleSimpleAttribute<MultipleInheritanceAttr>(S, D, Attr); break;
case AttributeList::AT_VirtualInheritance:
- handleInheritanceAttr(S, D, Attr);
- break;
+ handleSimpleAttribute<VirtualInheritanceAttr>(S, D, Attr); break;
case AttributeList::AT_Win64:
- handleWin64Attr(S, D, Attr); break;
+ handleSimpleAttribute<Win64Attr>(S, D, Attr); break;
case AttributeList::AT_ForceInline:
- handleForceInlineAttr(S, D, Attr);
- break;
+ handleSimpleAttribute<ForceInlineAttr>(S, D, Attr); break;
case AttributeList::AT_SelectAny:
- handleSelectAnyAttr(S, D, Attr);
- break;
+ handleSimpleAttribute<SelectAnyAttr>(S, D, Attr); break;
// Thread safety attributes:
case AttributeList::AT_AssertExclusiveLock:
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
void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
emitSourceFileHeader("Parsed attribute helpers", OS);
ParsedAttrMap Attrs = getParsedAttrList(Records);
- // Generate the default appertainsTo diagnostic method.
+ // Generate the default appertainsTo and language option diagnostic methods.
GenerateDefaultAppertainsTo(OS);
+ GenerateDefaultLangOptRequirements(OS);
// Generate the appertainsTo diagnostic methods and write their names into
// another mapping. At the same time, generate the AttrInfoMap object
emitArgInfo(*I->second, SS);
SS << ", " << I->second->getValueAsBit("HasCustomParsing");
SS << ", " << GenerateAppertainsTo(*I->second, OS);
+ SS << ", " << GenerateLangOptRequirements(*I->second, OS);
SS << " }";
if (I + 1 != E)