https://github.com/dingxiangfei2009 updated https://github.com/llvm/llvm-project/pull/143424
>From 830f4e9503e1bc48521dc38397b95546bbcaebe2 Mon Sep 17 00:00:00 2001 From: Xiangfei Ding <dingxiangfei2...@protonmail.ch> Date: Mon, 9 Jun 2025 13:57:18 +0000 Subject: [PATCH 1/2] [clang-c] introduce queries on GCC-style inline assembly statements We strive for exposing such information using existing stable ABIs. In doing so, queries are limited to what the original source holds or the LLVM IR `asm` block would expose in connection with attributes that the queries are concerned. Signed-off-by: Xiangfei Ding <dingxiangfei2...@protonmail.ch> --- clang/include/clang-c/Index.h | 94 +++++++++++++++++- clang/test/Index/inline-assembly.c | 48 +++++++++ clang/tools/c-index-test/c-index-test.c | 52 ++++++++++ clang/tools/libclang/CIndex.cpp | 125 ++++++++++++++++++++++-- clang/tools/libclang/libclang.map | 10 ++ 5 files changed, 321 insertions(+), 8 deletions(-) create mode 100644 clang/test/Index/inline-assembly.c diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index e4cb4327fbaac..06732f5942843 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -36,7 +36,7 @@ #define CINDEX_VERSION_MAJOR 0 #define CINDEX_VERSION_MINOR 64 -#define CINDEX_VERSION_ENCODE(major, minor) (((major)*10000) + ((minor)*1)) +#define CINDEX_VERSION_ENCODE(major, minor) (((major) * 10000) + ((minor) * 1)) #define CINDEX_VERSION \ CINDEX_VERSION_ENCODE(CINDEX_VERSION_MAJOR, CINDEX_VERSION_MINOR) @@ -4495,6 +4495,98 @@ CINDEX_LINKAGE CXStringSet *clang_Cursor_getCXXManglings(CXCursor); */ CINDEX_LINKAGE CXStringSet *clang_Cursor_getObjCManglings(CXCursor); +/** + * @} + */ + +/** + * \defgroup CINDEX_MODULE Inline Assembly introspection + * + * The functions in this group provide access to information about GCC-style + * inline assembly statements. + * + * @{ + */ + +/** + * Given a CXCursor_GCCAsmStmt cursor, return the assembly template string. + * As per LLVM IR Assembly Template language, template placeholders for + * inputs and outputs are either of the form $N where N is a decimal number + * as an index into the input-output specification, + * or ${N:M} where N is a decimal number also as an index into the + * input-output specification and M is the template argument modifier. + * The index N in both cases points into the the total inputs and outputs, + * or more specifically, into the list of outputs followed by the inputs, + * starting from index 0 as the first available template argument. + */ + +CINDEX_LINKAGE CXString clang_Cursor_getGCCAssemblyTemplate(CXCursor); + +/** + * Given a CXCursor_GCCAsmStmt cursor, check if the assembly block has goto + * labels. + */ + +CINDEX_LINKAGE unsigned clang_Cursor_isGCCAssemblyHasGoto(CXCursor); + +/** + * Given a CXCursor_GCCAsmStmt cursor, count the number of outputs + */ + +CINDEX_LINKAGE unsigned clang_Cursor_getGCCAssemblyNumOutputs(CXCursor); + +/** + * Given a CXCursor_GCCAsmStmt cursor, count the number of inputs + */ + +CINDEX_LINKAGE unsigned clang_Cursor_getGCCAssemblyNumInputs(CXCursor); + +/** + * Given a CXCursor_GCCAsmStmt cursor, get the constraint and expression cursor + * to the Index-th input. + */ + +CINDEX_LINKAGE unsigned clang_Cursor_getGCCAssemblyInput(CXCursor Cursor, + unsigned Index, + CXString *Constraint, + CXCursor *Expr); + +/** + * Given a CXCursor_GCCAsmStmt cursor, get the constraint and expression cursor + * to the Index-th output. + */ + +CINDEX_LINKAGE unsigned clang_Cursor_getGCCAssemblyOutput(CXCursor Cursor, + unsigned Index, + CXString *Constraint, + CXCursor *Expr); + +/** + * Given a CXCursor_GCCAsmStmt cursor, count the clobbers in it. + */ + +CINDEX_LINKAGE unsigned clang_Cursor_getGCCAssemblyNumClobbers(CXCursor Cursor); + +/** + * Given a CXCursor_GCCAsmStmt cursor, get the Index-th clobber of it. + */ + +CINDEX_LINKAGE CXString clang_Cursor_getGCCAssemblyClobber(CXCursor Cursor, + unsigned Index); + +/** + * Given a CXCursor_GCCAsmStmt cursor, check if the inline assembly is simple. + */ + +CINDEX_LINKAGE unsigned clang_Cursor_isGCCAssemblySimple(CXCursor Cursor); + +/** + * Given a CXCursor_GCCAsmStmt cursor, check if the inline assembly is + * `volatile`. + */ + +CINDEX_LINKAGE unsigned clang_Cursor_isGCCAssemblyVolatile(CXCursor Cursor); + /** * @} */ diff --git a/clang/test/Index/inline-assembly.c b/clang/test/Index/inline-assembly.c new file mode 100644 index 0000000000000..2223dd2985f51 --- /dev/null +++ b/clang/test/Index/inline-assembly.c @@ -0,0 +1,48 @@ +static void inline_assembly_template_regardless_of_target_machine() { + int tmp; + asm volatile ( + "nop\n" + "a_value %w[v]\n" + "o_value %w[o]" + : [v] "=&r" (tmp) + : [o] "r" (tmp) + : "cc", "memory" + ); +} + +// RUN: c-index-test -test-inline-assembly %s 2>&1 | FileCheck %s +// CHECK: ===ASM TEMPLATE=== +// CHECK: nop +// CHECK: a_value ${0:w} +// CHECK: o_value ${1:w} +// CHECK: ===ASM TEMPLATE END=== +// CHECK: volatile: true +// CHECK: simple: false +// CHECK: Output #0 Constraint (=&r): DeclRefExpr=tmp:2:9 +// CHECK: Input #0 Constraint (r): UnexposedExpr=tmp:2:9 +// CHECK: Clobber #0: cc +// CHECK: Clobber #1: memory +// CHECK: ===ASM END=== + +static void inline_assembly_valid_x86_example() { + int tmp; + asm ( + "nop\n" + "mov %w[o], %w[v]" + : [v] "=&r" (tmp) + : [o] "r" (tmp) + : "cc", "memory" + ); +} + +// CHECK: ===ASM TEMPLATE=== +// CHECK: nop +// CHECK: mov ${1:w}, ${0:w} +// CHECK: ===ASM TEMPLATE END=== +// CHECK: volatile: false +// CHECK: simple: false +// CHECK: Output #0 Constraint (=&r): DeclRefExpr=tmp:28:9 +// CHECK: Input #0 Constraint (r): UnexposedExpr=tmp:28:9 +// CHECK: Clobber #0: cc +// CHECK: Clobber #1: memory +// CHECK: ===ASM END=== diff --git a/clang/tools/c-index-test/c-index-test.c b/clang/tools/c-index-test/c-index-test.c index 4a887cd0c1e2e..0917439898f98 100644 --- a/clang/tools/c-index-test/c-index-test.c +++ b/clang/tools/c-index-test/c-index-test.c @@ -1988,6 +1988,53 @@ static enum CXChildVisitResult PrintDeclAttributes(CXCursor cursor, CXCursor p, return CXChildVisit_Continue; } +/******************************************************************************/ +/* Inline assembly cursor testing */ +/******************************************************************************/ + +static enum CXChildVisitResult +PrintGCCInlineAssembly(CXCursor cursor, CXCursor p, CXClientData d) { + CXString Constraint, Template, Clobber; + CXCursor Expr; + unsigned hasGoto, i, e; + if (clang_getCursorKind(cursor) != CXCursor_AsmStmt) { + return CXChildVisit_Recurse; + } + hasGoto = clang_Cursor_isGCCAssemblyHasGoto(cursor); + printf("===ASM TEMPLATE%s===\n", hasGoto ? " (WITH GOTO)" : ""); + Template = clang_Cursor_getGCCAssemblyTemplate(cursor); + printf("%s", clang_getCString(Template)); + clang_disposeString(Template); + printf("\n===ASM TEMPLATE END===\n"); + + printf("volatile: %s\n", + clang_Cursor_isGCCAssemblyVolatile(cursor) ? "true" : "false"); + printf("simple: %s\n", + clang_Cursor_isGCCAssemblySimple(cursor) ? "true" : "false"); + + for (i = 0, e = clang_Cursor_getGCCAssemblyNumOutputs(cursor); i < e; ++i) { + clang_Cursor_getGCCAssemblyOutput(cursor, i, &Constraint, &Expr); + printf("Output #%d Constraint (%s): ", i, clang_getCString(Constraint)); + PrintCursor(Expr, NULL); + printf("\n"); + clang_disposeString(Constraint); + } + for (i = 0, e = clang_Cursor_getGCCAssemblyNumInputs(cursor); i < e; ++i) { + clang_Cursor_getGCCAssemblyInput(cursor, i, &Constraint, &Expr); + printf("Input #%d Constraint (%s): ", i, clang_getCString(Constraint)); + PrintCursor(Expr, NULL); + printf("\n"); + clang_disposeString(Constraint); + } + for (i = 0, e = clang_Cursor_getGCCAssemblyNumClobbers(cursor); i < e; ++i) { + Clobber = clang_Cursor_getGCCAssemblyClobber(cursor, i); + printf("Clobber #%d: %s\n", i, clang_getCString(Clobber)); + clang_disposeString(Constraint); + } + printf("===ASM END===\n"); + return CXChildVisit_Recurse; +} + /******************************************************************************/ /* Target information testing. */ /******************************************************************************/ @@ -5010,6 +5057,7 @@ static void print_usage(void) { " c-index-test -test-annotate-tokens=<range> {<args>}*\n" " c-index-test -test-inclusion-stack-source {<args>}*\n" " c-index-test -test-inclusion-stack-tu <AST file>\n"); + fprintf(stderr, " c-index-test -test-inline-assembly <AST file>\n"); fprintf(stderr, " c-index-test -test-print-linkage-source {<args>}*\n" " c-index-test -test-print-visibility {<args>}*\n" @@ -5167,6 +5215,10 @@ int cindextest_main(int argc, const char **argv) { else if (argc > 2 && strstr(argv[1], "-single-symbol-sgf-for=") == argv[1]) return perform_test_single_symbol_sgf(argv[1], argc - 2, argv + 2); + if (argc > 2 && strstr(argv[1], "-test-inline-assembly") == argv[1]) + return perform_test_load_source(argc - 2, argv + 2, "all", + PrintGCCInlineAssembly, NULL); + print_usage(); return 1; } diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 3068621d9c004..3d7aa19c10645 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -2141,8 +2141,7 @@ class EnqueueVisitor : public ConstStmtVisitor<EnqueueVisitor, void>, void VisitBlockExpr(const BlockExpr *B); void VisitCompoundLiteralExpr(const CompoundLiteralExpr *E); void VisitCompoundStmt(const CompoundStmt *S); - void VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E) { /* Do nothing. */ - } + void VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E) { /* Do nothing. */ } void VisitMSDependentExistsStmt(const MSDependentExistsStmt *S); void VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *E); void VisitCXXNewExpr(const CXXNewExpr *E); @@ -2252,8 +2251,8 @@ class EnqueueVisitor : public ConstStmtVisitor<EnqueueVisitor, void>, void VisitOMPMaskedTaskLoopDirective(const OMPMaskedTaskLoopDirective *D); void VisitOMPMasterTaskLoopSimdDirective(const OMPMasterTaskLoopSimdDirective *D); - void VisitOMPMaskedTaskLoopSimdDirective( - const OMPMaskedTaskLoopSimdDirective *D); + void + VisitOMPMaskedTaskLoopSimdDirective(const OMPMaskedTaskLoopSimdDirective *D); void VisitOMPParallelMasterTaskLoopDirective( const OMPParallelMasterTaskLoopDirective *D); void VisitOMPParallelMaskedTaskLoopDirective( @@ -2811,8 +2810,7 @@ void OMPClauseEnqueue::VisitOMPXDynCGroupMemClause( void OMPClauseEnqueue::VisitOMPDoacrossClause(const OMPDoacrossClause *C) { VisitOMPClauseList(C); } -void OMPClauseEnqueue::VisitOMPXAttributeClause(const OMPXAttributeClause *C) { -} +void OMPClauseEnqueue::VisitOMPXAttributeClause(const OMPXAttributeClause *C) {} void OMPClauseEnqueue::VisitOMPXBareClause(const OMPXBareClause *C) {} } // namespace @@ -5290,7 +5288,7 @@ typedef struct _CXChildVisitResult { int reserved; enum CXChildVisitResult (*invoke)(struct _CXChildVisitResult *, CXCursor, CXCursor); -} * CXCursorVisitorBlock; +} *CXCursorVisitorBlock; static enum CXChildVisitResult visitWithBlock(CXCursor cursor, CXCursor parent, CXClientData client_data) { @@ -8648,6 +8646,119 @@ void clang_annotateTokens(CXTranslationUnit TU, CXToken *Tokens, } } +//===----------------------------------------------------------------------===// +// Operations for querying information of a GCC inline assembly block under a +// cursor. +//===----------------------------------------------------------------------===// +CXString clang_Cursor_getGCCAssemblyTemplate(CXCursor Cursor) { + if (!clang_isStatement(Cursor.kind)) + return cxstring::createEmpty(); + if (auto const *Stmt = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor))) { + auto const &C = getCursorContext(Cursor); + auto AsmTemplate = Stmt->generateAsmString(C); + return cxstring::createDup(AsmTemplate); + } + return cxstring::createEmpty(); +} + +unsigned clang_Cursor_isGCCAssemblyHasGoto(CXCursor Cursor) { + if (!clang_isStatement(Cursor.kind)) + return 0; + if (auto const *Stmt = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor))) { + return Stmt->isAsmGoto(); + } + return 0; +} + +unsigned clang_Cursor_getGCCAssemblyNumOutputs(CXCursor Cursor) { + if (!clang_isStatement(Cursor.kind)) + return 0; + if (auto const *Stmt = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor))) { + return Stmt->getNumOutputs(); + } + return 0; +} + +unsigned clang_Cursor_getGCCAssemblyNumInputs(CXCursor Cursor) { + if (!clang_isStatement(Cursor.kind)) + return 0; + if (auto const *Stmt = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor))) { + return Stmt->getNumInputs(); + } + return 0; +} + +unsigned clang_Cursor_getGCCAssemblyInput(CXCursor Cursor, unsigned Index, + CXString *Constraint, + CXCursor *Expr) { + if (!clang_isStatement(Cursor.kind) || !Constraint || !Expr) + return 0; + if (auto const *Stmt = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor)); + Stmt && Index < Stmt->getNumInputs()) { + auto Constraint_ = Stmt->getInputConstraint(Index); + auto const *Expr_ = Stmt->getInputExpr(Index); + *Constraint = cxstring::createDup(Constraint_); + *Expr = MakeCXCursor(Expr_, getCursorDecl(Cursor), + cxcursor::getCursorTU(Cursor)); + return 1; + } + return 0; +} + +unsigned clang_Cursor_getGCCAssemblyOutput(CXCursor Cursor, unsigned Index, + CXString *Constraint, + CXCursor *Expr) { + if (!clang_isStatement(Cursor.kind) || !Constraint || !Expr) + return 0; + if (auto const *Stmt = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor)); + Stmt && Index < Stmt->getNumOutputs()) { + auto Constraint_ = Stmt->getOutputConstraint(Index); + auto const *Expr_ = Stmt->getOutputExpr(Index); + *Constraint = cxstring::createDup(Constraint_); + *Expr = MakeCXCursor(Expr_, getCursorDecl(Cursor), + cxcursor::getCursorTU(Cursor)); + return 1; + } + return 0; +} + +unsigned clang_Cursor_getGCCAssemblyNumClobbers(CXCursor Cursor) { + if (!clang_isStatement(Cursor.kind)) + return 0; + if (auto const *Stmt = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor))) { + return Stmt->getNumClobbers(); + } + return 0; +} + +CXString clang_Cursor_getGCCAssemblyClobber(CXCursor Cursor, unsigned Index) { + if (!clang_isStatement(Cursor.kind)) + return cxstring::createEmpty(); + if (auto const *Stmt = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor)); + Stmt && Stmt->getNumClobbers()) { + return cxstring::createDup(Stmt->getClobber(Index)); + } + return cxstring::createEmpty(); +} + +unsigned clang_Cursor_isGCCAssemblySimple(CXCursor Cursor) { + if (!clang_isStatement(Cursor.kind)) + return 0; + if (auto const *Stmt = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor))) { + return Stmt->isSimple(); + } + return 0; +} + +unsigned clang_Cursor_isGCCAssemblyVolatile(CXCursor Cursor) { + if (!clang_isStatement(Cursor.kind)) + return 0; + if (auto const *Stmt = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor))) { + return Stmt->isVolatile(); + } + return 0; +} + //===----------------------------------------------------------------------===// // Operations for querying linkage of a cursor. //===----------------------------------------------------------------------===// diff --git a/clang/tools/libclang/libclang.map b/clang/tools/libclang/libclang.map index f08d13c3da9e1..b3a12e9e9834b 100644 --- a/clang/tools/libclang/libclang.map +++ b/clang/tools/libclang/libclang.map @@ -441,6 +441,16 @@ LLVM_20 { LLVM_21 { global: clang_getFullyQualifiedName; + clang_Cursor_getGCCAssemblyTemplate; + clang_Cursor_isGCCAssemblyHasGoto; + clang_Cursor_getGCCAssemblyNumOutputs; + clang_Cursor_getGCCAssemblyNumInputs; + clang_Cursor_getGCCAssemblyInput; + clang_Cursor_getGCCAssemblyOutput; + clang_Cursor_getGCCAssemblyNumClobbers; + clang_Cursor_getGCCAssemblyClobber; + clang_Cursor_isGCCAssemblySimple; + clang_Cursor_isGCCAssemblyVolatile; }; # Example of how to add a new symbol version entry. If you do add a new symbol >From 199ddbd303888c48109d756b5f3d77371ca1e072 Mon Sep 17 00:00:00 2001 From: Xiangfei Ding <dingxiangfei2...@protonmail.ch> Date: Fri, 20 Jun 2025 08:38:23 +0000 Subject: [PATCH 2/2] apply suggestions --- clang/docs/ReleaseNotes.rst | 3 + clang/include/clang-c/Index.h | 35 ++++++++--- clang/test/Index/inline-assembly.c | 6 +- clang/tools/c-index-test/c-index-test.c | 6 +- clang/tools/libclang/CIndex.cpp | 79 ++++++++++--------------- clang/tools/libclang/libclang.map | 1 - 6 files changed, 66 insertions(+), 64 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 96477ef6ddc9a..239ecd02a14f1 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -327,6 +327,9 @@ Non-comprehensive list of changes in this release ``__reference_constructs_from_temporary`` should be used instead. (#GH44056) - Added `__builtin_get_vtable_pointer` to directly load the primary vtable pointer from a polymorphic object. +- `libclang` receives a family of new bindings to query basic facts about + GCC-style inline assembly blocks, including whether the block is `volatile` + and its template string following the LLVM IR `asm` format. (#GH143424) - Clang no longer rejects reinterpret_cast conversions between indirect ARC-managed pointers and other pointer types. The prior behavior was overly strict and inconsistent with the ARC specification. diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index 06732f5942843..b04d2b6767e00 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -4518,6 +4518,9 @@ CINDEX_LINKAGE CXStringSet *clang_Cursor_getObjCManglings(CXCursor); * The index N in both cases points into the the total inputs and outputs, * or more specifically, into the list of outputs followed by the inputs, * starting from index 0 as the first available template argument. + * + * This function also returns a valid empty string if the cursor does not point + * at a GCC inline assembly block. */ CINDEX_LINKAGE CXString clang_Cursor_getGCCAssemblyTemplate(CXCursor); @@ -4525,18 +4528,24 @@ CINDEX_LINKAGE CXString clang_Cursor_getGCCAssemblyTemplate(CXCursor); /** * Given a CXCursor_GCCAsmStmt cursor, check if the assembly block has goto * labels. + * This function also returns FALSE if the cursor does not point at a GCC inline + * assembly block. */ CINDEX_LINKAGE unsigned clang_Cursor_isGCCAssemblyHasGoto(CXCursor); /** - * Given a CXCursor_GCCAsmStmt cursor, count the number of outputs + * Given a CXCursor_GCCAsmStmt cursor, count the number of outputs. + * This function also returns 0 if the cursor does not point at a GCC inline + * assembly block. */ CINDEX_LINKAGE unsigned clang_Cursor_getGCCAssemblyNumOutputs(CXCursor); /** - * Given a CXCursor_GCCAsmStmt cursor, count the number of inputs + * Given a CXCursor_GCCAsmStmt cursor, count the number of inputs. + * This function also returns 0 if the cursor does not point at a GCC inline + * assembly block. */ CINDEX_LINKAGE unsigned clang_Cursor_getGCCAssemblyNumInputs(CXCursor); @@ -4544,6 +4553,11 @@ CINDEX_LINKAGE unsigned clang_Cursor_getGCCAssemblyNumInputs(CXCursor); /** * Given a CXCursor_GCCAsmStmt cursor, get the constraint and expression cursor * to the Index-th input. + * This function returns TRUE when the cursor points at a GCC inline assembly + * statement, `Index` is within bounds and both the `Constraint` and `Expr` are + * not NULL. + * Otherwise, this function returns FALSE but leaves `Constraint` and `Expr` + * intact. */ CINDEX_LINKAGE unsigned clang_Cursor_getGCCAssemblyInput(CXCursor Cursor, @@ -4554,6 +4568,11 @@ CINDEX_LINKAGE unsigned clang_Cursor_getGCCAssemblyInput(CXCursor Cursor, /** * Given a CXCursor_GCCAsmStmt cursor, get the constraint and expression cursor * to the Index-th output. + * This function returns TRUE when the cursor points at a GCC inline assembly + * statement, `Index` is within bounds and both the `Constraint` and `Expr` are + * not NULL. + * Otherwise, this function returns FALSE but leaves `Constraint` and `Expr` + * intact. */ CINDEX_LINKAGE unsigned clang_Cursor_getGCCAssemblyOutput(CXCursor Cursor, @@ -4563,26 +4582,26 @@ CINDEX_LINKAGE unsigned clang_Cursor_getGCCAssemblyOutput(CXCursor Cursor, /** * Given a CXCursor_GCCAsmStmt cursor, count the clobbers in it. + * This function also returns 0 if the cursor does not point at a GCC inline + * assembly block. */ CINDEX_LINKAGE unsigned clang_Cursor_getGCCAssemblyNumClobbers(CXCursor Cursor); /** * Given a CXCursor_GCCAsmStmt cursor, get the Index-th clobber of it. + * This function returns a valid empty string if the cursor does not point + * at a GCC inline assembly block or `Index` is out of bounds. */ CINDEX_LINKAGE CXString clang_Cursor_getGCCAssemblyClobber(CXCursor Cursor, unsigned Index); -/** - * Given a CXCursor_GCCAsmStmt cursor, check if the inline assembly is simple. - */ - -CINDEX_LINKAGE unsigned clang_Cursor_isGCCAssemblySimple(CXCursor Cursor); - /** * Given a CXCursor_GCCAsmStmt cursor, check if the inline assembly is * `volatile`. + * This function returns FALSE if the cursor does not point at a GCC inline + * assembly block. */ CINDEX_LINKAGE unsigned clang_Cursor_isGCCAssemblyVolatile(CXCursor Cursor); diff --git a/clang/test/Index/inline-assembly.c b/clang/test/Index/inline-assembly.c index 2223dd2985f51..64a7ce03852c9 100644 --- a/clang/test/Index/inline-assembly.c +++ b/clang/test/Index/inline-assembly.c @@ -17,7 +17,6 @@ static void inline_assembly_template_regardless_of_target_machine() { // CHECK: o_value ${1:w} // CHECK: ===ASM TEMPLATE END=== // CHECK: volatile: true -// CHECK: simple: false // CHECK: Output #0 Constraint (=&r): DeclRefExpr=tmp:2:9 // CHECK: Input #0 Constraint (r): UnexposedExpr=tmp:2:9 // CHECK: Clobber #0: cc @@ -40,9 +39,8 @@ static void inline_assembly_valid_x86_example() { // CHECK: mov ${1:w}, ${0:w} // CHECK: ===ASM TEMPLATE END=== // CHECK: volatile: false -// CHECK: simple: false -// CHECK: Output #0 Constraint (=&r): DeclRefExpr=tmp:28:9 -// CHECK: Input #0 Constraint (r): UnexposedExpr=tmp:28:9 +// CHECK: Output #0 Constraint (=&r): DeclRefExpr=tmp:27:9 +// CHECK: Input #0 Constraint (r): UnexposedExpr=tmp:27:9 // CHECK: Clobber #0: cc // CHECK: Clobber #1: memory // CHECK: ===ASM END=== diff --git a/clang/tools/c-index-test/c-index-test.c b/clang/tools/c-index-test/c-index-test.c index 0917439898f98..07566ff77158f 100644 --- a/clang/tools/c-index-test/c-index-test.c +++ b/clang/tools/c-index-test/c-index-test.c @@ -1997,9 +1997,9 @@ PrintGCCInlineAssembly(CXCursor cursor, CXCursor p, CXClientData d) { CXString Constraint, Template, Clobber; CXCursor Expr; unsigned hasGoto, i, e; - if (clang_getCursorKind(cursor) != CXCursor_AsmStmt) { + if (clang_getCursorKind(cursor) != CXCursor_AsmStmt) return CXChildVisit_Recurse; - } + hasGoto = clang_Cursor_isGCCAssemblyHasGoto(cursor); printf("===ASM TEMPLATE%s===\n", hasGoto ? " (WITH GOTO)" : ""); Template = clang_Cursor_getGCCAssemblyTemplate(cursor); @@ -2009,8 +2009,6 @@ PrintGCCInlineAssembly(CXCursor cursor, CXCursor p, CXClientData d) { printf("volatile: %s\n", clang_Cursor_isGCCAssemblyVolatile(cursor) ? "true" : "false"); - printf("simple: %s\n", - clang_Cursor_isGCCAssemblySimple(cursor) ? "true" : "false"); for (i = 0, e = clang_Cursor_getGCCAssemblyNumOutputs(cursor); i < e; ++i) { clang_Cursor_getGCCAssemblyOutput(cursor, i, &Constraint, &Expr); diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 3d7aa19c10645..5a0b0e133479d 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -8653,9 +8653,9 @@ void clang_annotateTokens(CXTranslationUnit TU, CXToken *Tokens, CXString clang_Cursor_getGCCAssemblyTemplate(CXCursor Cursor) { if (!clang_isStatement(Cursor.kind)) return cxstring::createEmpty(); - if (auto const *Stmt = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor))) { - auto const &C = getCursorContext(Cursor); - auto AsmTemplate = Stmt->generateAsmString(C); + if (auto const *S = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor))) { + ASTContext const &C = getCursorContext(Cursor); + std::string AsmTemplate = S->generateAsmString(C); return cxstring::createDup(AsmTemplate); } return cxstring::createEmpty(); @@ -8664,42 +8664,39 @@ CXString clang_Cursor_getGCCAssemblyTemplate(CXCursor Cursor) { unsigned clang_Cursor_isGCCAssemblyHasGoto(CXCursor Cursor) { if (!clang_isStatement(Cursor.kind)) return 0; - if (auto const *Stmt = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor))) { - return Stmt->isAsmGoto(); - } + if (auto const *S = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor))) + return S->isAsmGoto(); return 0; } unsigned clang_Cursor_getGCCAssemblyNumOutputs(CXCursor Cursor) { if (!clang_isStatement(Cursor.kind)) return 0; - if (auto const *Stmt = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor))) { - return Stmt->getNumOutputs(); - } + if (auto const *S = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor))) + return S->getNumOutputs(); return 0; } unsigned clang_Cursor_getGCCAssemblyNumInputs(CXCursor Cursor) { if (!clang_isStatement(Cursor.kind)) return 0; - if (auto const *Stmt = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor))) { - return Stmt->getNumInputs(); - } + if (auto const *S = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor))) + return S->getNumInputs(); return 0; } unsigned clang_Cursor_getGCCAssemblyInput(CXCursor Cursor, unsigned Index, CXString *Constraint, - CXCursor *Expr) { - if (!clang_isStatement(Cursor.kind) || !Constraint || !Expr) + CXCursor *ExprCursor) { + if (!clang_isStatement(Cursor.kind) || !Constraint || !ExprCursor) return 0; - if (auto const *Stmt = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor)); - Stmt && Index < Stmt->getNumInputs()) { - auto Constraint_ = Stmt->getInputConstraint(Index); - auto const *Expr_ = Stmt->getInputExpr(Index); + if (auto const *S = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor)); + S && Index < S->getNumInputs()) { + std::string Constraint_ = S->getInputConstraint(Index); + Expr const *E = S->getInputExpr(Index); *Constraint = cxstring::createDup(Constraint_); - *Expr = MakeCXCursor(Expr_, getCursorDecl(Cursor), - cxcursor::getCursorTU(Cursor)); + *ExprCursor = + MakeCXCursor(E, getCursorDecl(Cursor), cxcursor::getCursorTU(Cursor)); return 1; } return 0; @@ -8707,16 +8704,16 @@ unsigned clang_Cursor_getGCCAssemblyInput(CXCursor Cursor, unsigned Index, unsigned clang_Cursor_getGCCAssemblyOutput(CXCursor Cursor, unsigned Index, CXString *Constraint, - CXCursor *Expr) { - if (!clang_isStatement(Cursor.kind) || !Constraint || !Expr) + CXCursor *ExprCursor) { + if (!clang_isStatement(Cursor.kind) || !Constraint || !ExprCursor) return 0; - if (auto const *Stmt = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor)); - Stmt && Index < Stmt->getNumOutputs()) { - auto Constraint_ = Stmt->getOutputConstraint(Index); - auto const *Expr_ = Stmt->getOutputExpr(Index); + if (auto const *S = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor)); + S && Index < S->getNumOutputs()) { + std::string Constraint_ = S->getOutputConstraint(Index); + Expr const *E = S->getOutputExpr(Index); *Constraint = cxstring::createDup(Constraint_); - *Expr = MakeCXCursor(Expr_, getCursorDecl(Cursor), - cxcursor::getCursorTU(Cursor)); + *ExprCursor = + MakeCXCursor(E, getCursorDecl(Cursor), cxcursor::getCursorTU(Cursor)); return 1; } return 0; @@ -8725,37 +8722,25 @@ unsigned clang_Cursor_getGCCAssemblyOutput(CXCursor Cursor, unsigned Index, unsigned clang_Cursor_getGCCAssemblyNumClobbers(CXCursor Cursor) { if (!clang_isStatement(Cursor.kind)) return 0; - if (auto const *Stmt = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor))) { - return Stmt->getNumClobbers(); - } + if (auto const *S = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor))) + return S->getNumClobbers(); return 0; } CXString clang_Cursor_getGCCAssemblyClobber(CXCursor Cursor, unsigned Index) { if (!clang_isStatement(Cursor.kind)) return cxstring::createEmpty(); - if (auto const *Stmt = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor)); - Stmt && Stmt->getNumClobbers()) { - return cxstring::createDup(Stmt->getClobber(Index)); - } + if (auto const *S = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor)); + S && S->getNumClobbers()) + return cxstring::createDup(S->getClobber(Index)); return cxstring::createEmpty(); } -unsigned clang_Cursor_isGCCAssemblySimple(CXCursor Cursor) { - if (!clang_isStatement(Cursor.kind)) - return 0; - if (auto const *Stmt = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor))) { - return Stmt->isSimple(); - } - return 0; -} - unsigned clang_Cursor_isGCCAssemblyVolatile(CXCursor Cursor) { if (!clang_isStatement(Cursor.kind)) return 0; - if (auto const *Stmt = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor))) { - return Stmt->isVolatile(); - } + if (auto const *S = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor))) + return S->isVolatile(); return 0; } diff --git a/clang/tools/libclang/libclang.map b/clang/tools/libclang/libclang.map index b3a12e9e9834b..d140a71e771a0 100644 --- a/clang/tools/libclang/libclang.map +++ b/clang/tools/libclang/libclang.map @@ -449,7 +449,6 @@ LLVM_21 { clang_Cursor_getGCCAssemblyOutput; clang_Cursor_getGCCAssemblyNumClobbers; clang_Cursor_getGCCAssemblyClobber; - clang_Cursor_isGCCAssemblySimple; clang_Cursor_isGCCAssemblyVolatile; }; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits