diff options
Diffstat (limited to 'clang/lib/Sema/SemaDeclAttr.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 75 |
1 files changed, 62 insertions, 13 deletions
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index e76e7c6..7d21841 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -334,6 +334,26 @@ static bool checkFunctionOrMethodParameterIndex( return true; } +/// Check if the argument \p E is a ASCII string literal. If not emit an error +/// and return false, otherwise set \p Str to the value of the string literal +/// and return true. +bool Sema::checkStringLiteralArgumentAttr(const AttributeCommonInfo &CI, + const Expr *E, StringRef &Str, + SourceLocation *ArgLocation) { + const auto *Literal = dyn_cast<StringLiteral>(E->IgnoreParenCasts()); + if (ArgLocation) + *ArgLocation = E->getBeginLoc(); + + if (!Literal || !Literal->isAscii()) { + Diag(E->getBeginLoc(), diag::err_attribute_argument_type) + << CI << AANT_ArgumentString; + return false; + } + + Str = Literal->getString(); + return true; +} + /// Check if the argument \p ArgNum of \p Attr is a ASCII string literal. /// If not emit an error and return false. If the argument is an identifier it /// will emit an error with a fixit hint and treat it as if it was a string @@ -356,18 +376,7 @@ bool Sema::checkStringLiteralArgumentAttr(const ParsedAttr &AL, unsigned ArgNum, // Now check for an actual string literal. Expr *ArgExpr = AL.getArgAsExpr(ArgNum); - const auto *Literal = dyn_cast<StringLiteral>(ArgExpr->IgnoreParenCasts()); - if (ArgLocation) - *ArgLocation = ArgExpr->getBeginLoc(); - - if (!Literal || !Literal->isAscii()) { - Diag(ArgExpr->getBeginLoc(), diag::err_attribute_argument_type) - << AL << AANT_ArgumentString; - return false; - } - - Str = Literal->getString(); - return true; + return checkStringLiteralArgumentAttr(AL, ArgExpr, Str, ArgLocation); } /// Applies the given attribute to the Decl without performing any @@ -8123,6 +8132,37 @@ EnforceTCBLeafAttr *Sema::mergeEnforceTCBLeafAttr( // Top Level Sema Entry Points //===----------------------------------------------------------------------===// +// Returns true if the attribute must delay setting its arguments until after +// template instantiation, and false otherwise. +static bool MustDelayAttributeArguments(const ParsedAttr &AL) { + // Only attributes that accept expression parameter packs can delay arguments. + if (!AL.acceptsExprPack()) + return false; + + bool AttrHasVariadicArg = AL.hasVariadicArg(); + unsigned AttrNumArgs = AL.getNumArgMembers(); + for (size_t I = 0; I < std::min(AL.getNumArgs(), AttrNumArgs); ++I) { + bool IsLastAttrArg = I == (AttrNumArgs - 1); + // If the argument is the last argument and it is variadic it can contain + // any expression. + if (IsLastAttrArg && AttrHasVariadicArg) + return false; + Expr *E = AL.getArgAsExpr(I); + bool ArgMemberCanHoldExpr = AL.isParamExpr(I); + // If the expression is a pack expansion then arguments must be delayed + // unless the argument is an expression and it is the last argument of the + // attribute. + if (isa<PackExpansionExpr>(E)) + return !(IsLastAttrArg && ArgMemberCanHoldExpr); + // Last case is if the expression is value dependent then it must delay + // arguments unless the corresponding argument is able to hold the + // expression. + if (E->isValueDependent() && !ArgMemberCanHoldExpr) + return true; + } + return false; +} + /// ProcessDeclAttribute - Apply the specific attribute to the specified decl if /// the attribute applies to decls. If the attribute is a type attribute, just /// silently ignore it if a GNU attribute. @@ -8150,9 +8190,18 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, return; } - if (S.checkCommonAttributeFeatures(D, AL)) + // Check if argument population must delayed to after template instantiation. + bool MustDelayArgs = MustDelayAttributeArguments(AL); + + // Argument number check must be skipped if arguments are delayed. + if (S.checkCommonAttributeFeatures(D, AL, MustDelayArgs)) return; + if (MustDelayArgs) { + AL.handleAttrWithDelayedArgs(S, D); + return; + } + switch (AL.getKind()) { default: if (AL.getInfo().handleDeclAttribute(S, D, AL) != ParsedAttrInfo::NotHandled) |