diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 126 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 57 |
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) { |