summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp126
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiateDecl.cpp57
2 files changed, 149 insertions, 34 deletions
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index bf11ae98bcc..a0b4c53b1a7 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -245,11 +245,11 @@ static bool checkUInt32Argument(Sema &S, const AttrInfo &AI, const Expr *Expr,
!Expr->isIntegerConstantExpr(I, S.Context)) {
if (Idx != UINT_MAX)
S.Diag(getAttrLoc(AI), diag::err_attribute_argument_n_type)
- << AI << Idx << AANT_ArgumentIntegerConstant
+ << &AI << Idx << AANT_ArgumentIntegerConstant
<< Expr->getSourceRange();
else
S.Diag(getAttrLoc(AI), diag::err_attribute_argument_type)
- << AI << AANT_ArgumentIntegerConstant << Expr->getSourceRange();
+ << &AI << AANT_ArgumentIntegerConstant << Expr->getSourceRange();
return false;
}
@@ -261,7 +261,7 @@ static bool checkUInt32Argument(Sema &S, const AttrInfo &AI, const Expr *Expr,
if (StrictlyUnsigned && I.isSigned() && I.isNegative()) {
S.Diag(getAttrLoc(AI), diag::err_attribute_requires_positive_integer)
- << AI << /*non-negative*/ 1;
+ << &AI << /*non-negative*/ 1;
return false;
}
@@ -5853,57 +5853,115 @@ static void handleInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
}
}
-static void handleAMDGPUFlatWorkGroupSizeAttr(Sema &S, Decl *D,
- const ParsedAttr &AL) {
+static bool
+checkAMDGPUFlatWorkGroupSizeArguments(Sema &S, Expr *MinExpr, Expr *MaxExpr,
+ const AMDGPUFlatWorkGroupSizeAttr &Attr) {
+ // Accept template arguments for now as they depend on something else.
+ // We'll get to check them when they eventually get instantiated.
+ if (MinExpr->isValueDependent() || MaxExpr->isValueDependent())
+ return false;
+
uint32_t Min = 0;
- Expr *MinExpr = AL.getArgAsExpr(0);
- if (!checkUInt32Argument(S, AL, MinExpr, Min))
- return;
+ if (!checkUInt32Argument(S, Attr, MinExpr, Min, 0))
+ return true;
uint32_t Max = 0;
- Expr *MaxExpr = AL.getArgAsExpr(1);
- if (!checkUInt32Argument(S, AL, MaxExpr, Max))
- return;
+ if (!checkUInt32Argument(S, Attr, MaxExpr, Max, 1))
+ return true;
if (Min == 0 && Max != 0) {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_invalid) << AL << 0;
- return;
+ S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid)
+ << &Attr << 0;
+ return true;
}
if (Min > Max) {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_invalid) << AL << 1;
- return;
+ S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid)
+ << &Attr << 1;
+ return true;
}
- D->addAttr(::new (S.Context)
- AMDGPUFlatWorkGroupSizeAttr(AL.getLoc(), S.Context, Min, Max,
- AL.getAttributeSpellingListIndex()));
+ return false;
}
-static void handleAMDGPUWavesPerEUAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- uint32_t Min = 0;
- Expr *MinExpr = AL.getArgAsExpr(0);
- if (!checkUInt32Argument(S, AL, MinExpr, Min))
+void Sema::addAMDGPUFlatWorkGroupSizeAttr(SourceRange AttrRange, Decl *D,
+ Expr *MinExpr, Expr *MaxExpr,
+ unsigned SpellingListIndex) {
+ AMDGPUFlatWorkGroupSizeAttr TmpAttr(AttrRange, Context, MinExpr, MaxExpr,
+ SpellingListIndex);
+
+ if (checkAMDGPUFlatWorkGroupSizeArguments(*this, MinExpr, MaxExpr, TmpAttr))
return;
+ D->addAttr(::new (Context) AMDGPUFlatWorkGroupSizeAttr(
+ AttrRange, Context, MinExpr, MaxExpr, SpellingListIndex));
+}
+
+static void handleAMDGPUFlatWorkGroupSizeAttr(Sema &S, Decl *D,
+ const ParsedAttr &AL) {
+ Expr *MinExpr = AL.getArgAsExpr(0);
+ Expr *MaxExpr = AL.getArgAsExpr(1);
+
+ S.addAMDGPUFlatWorkGroupSizeAttr(AL.getRange(), D, MinExpr, MaxExpr,
+ AL.getAttributeSpellingListIndex());
+}
+
+static bool checkAMDGPUWavesPerEUArguments(Sema &S, Expr *MinExpr,
+ Expr *MaxExpr,
+ const AMDGPUWavesPerEUAttr &Attr) {
+ if (S.DiagnoseUnexpandedParameterPack(MinExpr) ||
+ (MaxExpr && S.DiagnoseUnexpandedParameterPack(MaxExpr)))
+ return true;
+
+ // Accept template arguments for now as they depend on something else.
+ // We'll get to check them when they eventually get instantiated.
+ if (MinExpr->isValueDependent() || (MaxExpr && MaxExpr->isValueDependent()))
+ return false;
+
+ uint32_t Min = 0;
+ if (!checkUInt32Argument(S, Attr, MinExpr, Min, 0))
+ return true;
+
uint32_t Max = 0;
- if (AL.getNumArgs() == 2) {
- Expr *MaxExpr = AL.getArgAsExpr(1);
- if (!checkUInt32Argument(S, AL, MaxExpr, Max))
- return;
- }
+ if (MaxExpr && !checkUInt32Argument(S, Attr, MaxExpr, Max, 1))
+ return true;
if (Min == 0 && Max != 0) {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_invalid) << AL << 0;
- return;
+ S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid)
+ << &Attr << 0;
+ return true;
}
if (Max != 0 && Min > Max) {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_invalid) << AL << 1;
- return;
+ S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid)
+ << &Attr << 1;
+ return true;
}
- D->addAttr(::new (S.Context)
- AMDGPUWavesPerEUAttr(AL.getLoc(), S.Context, Min, Max,
- AL.getAttributeSpellingListIndex()));
+ return false;
+}
+
+void Sema::addAMDGPUWavesPerEUAttr(SourceRange AttrRange, Decl *D,
+ Expr *MinExpr, Expr *MaxExpr,
+ unsigned SpellingListIndex) {
+ AMDGPUWavesPerEUAttr TmpAttr(AttrRange, Context, MinExpr, MaxExpr,
+ SpellingListIndex);
+
+ if (checkAMDGPUWavesPerEUArguments(*this, MinExpr, MaxExpr, TmpAttr))
+ return;
+
+ D->addAttr(::new (Context) AMDGPUWavesPerEUAttr(AttrRange, Context, MinExpr,
+ MaxExpr, SpellingListIndex));
+}
+
+static void handleAMDGPUWavesPerEUAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (!checkAttributeAtLeastNumArgs(S, AL, 1) ||
+ !checkAttributeAtMostNumArgs(S, AL, 2))
+ return;
+
+ Expr *MinExpr = AL.getArgAsExpr(0);
+ Expr *MaxExpr = (AL.getNumArgs() > 1) ? AL.getArgAsExpr(1) : nullptr;
+
+ S.addAMDGPUWavesPerEUAttr(AL.getRange(), D, MinExpr, MaxExpr,
+ AL.getAttributeSpellingListIndex());
}
static void handleAMDGPUNumSGPRAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 91a402d6d8d..db63529044b 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -344,6 +344,51 @@ static void instantiateOMPDeclareSimdDeclAttr(
Attr.getRange());
}
+static void instantiateDependentAMDGPUFlatWorkGroupSizeAttr(
+ Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
+ const AMDGPUFlatWorkGroupSizeAttr &Attr, Decl *New) {
+ // Both min and max expression are constant expressions.
+ EnterExpressionEvaluationContext Unevaluated(
+ S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
+
+ ExprResult Result = S.SubstExpr(Attr.getMin(), TemplateArgs);
+ if (Result.isInvalid())
+ return;
+ Expr *MinExpr = Result.getAs<Expr>();
+
+ Result = S.SubstExpr(Attr.getMax(), TemplateArgs);
+ if (Result.isInvalid())
+ return;
+ Expr *MaxExpr = Result.getAs<Expr>();
+
+ S.addAMDGPUFlatWorkGroupSizeAttr(Attr.getLocation(), New, MinExpr, MaxExpr,
+ Attr.getSpellingListIndex());
+}
+
+static void instantiateDependentAMDGPUWavesPerEUAttr(
+ Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
+ const AMDGPUWavesPerEUAttr &Attr, Decl *New) {
+ // Both min and max expression are constant expressions.
+ EnterExpressionEvaluationContext Unevaluated(
+ S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
+
+ ExprResult Result = S.SubstExpr(Attr.getMin(), TemplateArgs);
+ if (Result.isInvalid())
+ return;
+ Expr *MinExpr = Result.getAs<Expr>();
+
+ Expr *MaxExpr = nullptr;
+ if (auto Max = Attr.getMax()) {
+ Result = S.SubstExpr(Max, TemplateArgs);
+ if (Result.isInvalid())
+ return;
+ MaxExpr = Result.getAs<Expr>();
+ }
+
+ S.addAMDGPUWavesPerEUAttr(Attr.getLocation(), New, MinExpr, MaxExpr,
+ Attr.getSpellingListIndex());
+}
+
void Sema::InstantiateAttrsForDecl(
const MultiLevelTemplateArgumentList &TemplateArgs, const Decl *Tmpl,
Decl *New, LateInstantiatedAttrVec *LateAttrs,
@@ -437,6 +482,18 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
continue;
}
+ if (const AMDGPUFlatWorkGroupSizeAttr *AMDGPUFlatWorkGroupSize =
+ dyn_cast<AMDGPUFlatWorkGroupSizeAttr>(TmplAttr)) {
+ instantiateDependentAMDGPUFlatWorkGroupSizeAttr(
+ *this, TemplateArgs, *AMDGPUFlatWorkGroupSize, New);
+ }
+
+ if (const AMDGPUWavesPerEUAttr *AMDGPUFlatWorkGroupSize =
+ dyn_cast<AMDGPUWavesPerEUAttr>(TmplAttr)) {
+ instantiateDependentAMDGPUWavesPerEUAttr(*this, TemplateArgs,
+ *AMDGPUFlatWorkGroupSize, New);
+ }
+
// Existing DLL attribute on the instantiation takes precedence.
if (TmplAttr->getKind() == attr::DLLExport ||
TmplAttr->getKind() == attr::DLLImport) {
OpenPOWER on IntegriCloud