diff options
author | cor3ntin <corentinjabot@gmail.com> | 2025-03-17 20:10:46 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-03-17 20:10:46 +0100 |
commit | 911b200ce339ace2d55cd2827bb10ed6a494faae (patch) | |
tree | 7e6360734a4fcef3407b8fb8e3047288a270e690 /clang/lib/Parse/Parser.cpp | |
parent | 2443fe537f8bf7620c26586034b12a977d14e366 (diff) | |
download | llvm-911b200ce339ace2d55cd2827bb10ed6a494faae.zip llvm-911b200ce339ace2d55cd2827bb10ed6a494faae.tar.gz llvm-911b200ce339ace2d55cd2827bb10ed6a494faae.tar.bz2 |
[Clang] Constant Expressions inside of GCC' asm strings (#131003)
Implements GCC's constexpr string ASM extension
https://gcc.gnu.org/onlinedocs/gcc/Asm-constexprs.html
Diffstat (limited to 'clang/lib/Parse/Parser.cpp')
-rw-r--r-- | clang/lib/Parse/Parser.cpp | 41 |
1 files changed, 27 insertions, 14 deletions
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 0710542..83dd7b1 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -19,6 +19,7 @@ #include "clang/Basic/FileManager.h" #include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/DeclSpec.h" +#include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" #include "clang/Sema/SemaCodeCompletion.h" @@ -1668,28 +1669,40 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) { /// string-literal /// ExprResult Parser::ParseAsmStringLiteral(bool ForAsmLabel) { - if (!isTokenStringLiteral()) { - Diag(Tok, diag::err_expected_string_literal) - << /*Source='in...'*/0 << "'asm'"; - return ExprError(); - } - ExprResult AsmString(ParseStringLiteralExpression()); - if (!AsmString.isInvalid()) { + ExprResult AsmString; + if (isTokenStringLiteral()) { + AsmString = ParseStringLiteralExpression(); + if (AsmString.isInvalid()) + return AsmString; + const auto *SL = cast<StringLiteral>(AsmString.get()); if (!SL->isOrdinary()) { Diag(Tok, diag::err_asm_operand_wide_string_literal) - << SL->isWide() - << SL->getSourceRange(); + << SL->isWide() << SL->getSourceRange(); return ExprError(); } - if (ForAsmLabel && SL->getString().empty()) { - Diag(Tok, diag::err_asm_operand_wide_string_literal) - << 2 /* an empty */ << SL->getSourceRange(); + } else if (!ForAsmLabel && getLangOpts().CPlusPlus11 && + Tok.is(tok::l_paren)) { + ParenParseOption ExprType = SimpleExpr; + SourceLocation RParenLoc; + ParsedType CastTy; + + EnterExpressionEvaluationContext ConstantEvaluated( + Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated); + AsmString = ParseParenExpression(ExprType, true /*stopIfCastExpr*/, false, + CastTy, RParenLoc); + if (!AsmString.isInvalid()) + AsmString = Actions.ActOnConstantExpression(AsmString); + + if (AsmString.isInvalid()) return ExprError(); - } + } else { + Diag(Tok, diag::err_asm_expected_string) << /*and expression=*/( + (getLangOpts().CPlusPlus11 && !ForAsmLabel) ? 0 : 1); } - return AsmString; + + return Actions.ActOnGCCAsmStmtString(AsmString.get(), ForAsmLabel); } /// ParseSimpleAsm |