Index: clang/lib/CodeGen/CGStmt.cpp =================================================================== --- clang/lib/CodeGen/CGStmt.cpp +++ clang/lib/CodeGen/CGStmt.cpp @@ -1838,8 +1838,22 @@ // (immediate or symbolic), try to emit it as such. if (!Info.allowsRegister() && !Info.allowsMemory()) { if (Info.requiresImmediateConstant()) { - llvm::APSInt AsmConst = InputExpr->EvaluateKnownConstInt(getContext()); - return llvm::ConstantInt::get(getLLVMContext(), AsmConst); + Expr::EvalResult EVResult; + InputExpr->EvaluateAsRValue(EVResult, getContext(), true); + + llvm::APSInt IntResult; + if (EVResult.Val.isInt()) + IntResult = EVResult.Val.getInt(); + else if (EVResult.Val.isNullPointer()) + IntResult = llvm::APSInt::get( + getContext().getTargetNullPointerValue(InputExpr->getType())); + else if (EVResult.Val.isLValue() && !EVResult.Val.getLValueBase()) + IntResult = + llvm::APSInt::get(EVResult.Val.getLValueOffset().getQuantity()); + else + llvm_unreachable("Failed evaluate InputExpr as integer."); + + return llvm::ConstantInt::get(getLLVMContext(), IntResult); } Expr::EvalResult Result; Index: clang/lib/Sema/SemaStmtAsm.cpp =================================================================== --- clang/lib/Sema/SemaStmtAsm.cpp +++ clang/lib/Sema/SemaStmtAsm.cpp @@ -385,11 +385,27 @@ return StmtError( Diag(InputExpr->getBeginLoc(), diag::err_asm_immediate_expected) << Info.getConstraintStr() << InputExpr->getSourceRange()); - llvm::APSInt Result = EVResult.Val.getInt(); - if (!Info.isValidAsmImmediate(Result)) + + // For compatibility with GCC, we also allows pointers that would be + // integral constant expressions if they were cast to int. + llvm::APSInt IntResult; + if (EVResult.Val.isInt()) + IntResult = EVResult.Val.getInt(); + else if (EVResult.Val.isNullPointer()) + IntResult = llvm::APSInt::get( + Context.getTargetNullPointerValue(InputExpr->getType())); + else if (EVResult.Val.isLValue() && !EVResult.Val.getLValueBase()) + IntResult = + llvm::APSInt::get(EVResult.Val.getLValueOffset().getQuantity()); + else + return StmtError( + Diag(InputExpr->getBeginLoc(), diag::err_asm_immediate_expected) + << Info.getConstraintStr() << InputExpr->getSourceRange()); + + if (!Info.isValidAsmImmediate(IntResult)) return StmtError(Diag(InputExpr->getBeginLoc(), diag::err_invalid_asm_value_for_constraint) - << Result.toString(10) << Info.getConstraintStr() + << IntResult.toString(10) << Info.getConstraintStr() << InputExpr->getSourceRange()); } Index: clang/test/CodeGen/x86-64-inline-asm.c =================================================================== --- clang/test/CodeGen/x86-64-inline-asm.c +++ clang/test/CodeGen/x86-64-inline-asm.c @@ -1,6 +1,7 @@ // REQUIRES: x86-registered-target // RUN: %clang_cc1 -triple x86_64 %s -S -o /dev/null -DWARN -verify // RUN: %clang_cc1 -triple x86_64 %s -S -o /dev/null -Werror -verify +// RUN: %clang_cc1 -triple x86_64-linux-gnu %s -S -o - | FileCheck %s void f() { asm("movaps %xmm3, (%esi, 2)"); // expected-note@1 {{instantiated into assembly here}} @@ -15,3 +16,15 @@ void g(void) { asm volatile("movd %%xmm0, %0" : : "m"(var)); } + +void pr40890(void) { + struct s { + int a, b; + } s; + __asm__ __volatile__("\n#define S_A abcd%0\n" : : "n"(&((struct s*)0)->a)); + __asm__ __volatile__("\n#define S_B abcd%0\n" : : "n"(&((struct s*)0)->b)); + +// CHECK-LABEL: pr40890 +// CHECK: #define S_A abcd$0 +// CHECK: #define S_B abcd$4 +} Index: clang/test/Sema/inline-asm-validate-x86.c =================================================================== --- clang/test/Sema/inline-asm-validate-x86.c +++ clang/test/Sema/inline-asm-validate-x86.c @@ -137,3 +137,15 @@ : "0"(i), "O"(64)); // expected-no-error } +void pr40890(void) { + struct s { + int a, b; + }; + static struct s s; + // This null pointer can be used as an integer constant expression. + __asm__ __volatile__("\n#define S_A abcd%0\n" : : "n"(&((struct s*)0)->a)); + // This offset-from-null pointer can be used as an integer constant expression. + __asm__ __volatile__("\n#define S_B abcd%0\n" : : "n"(&((struct s*)0)->b)); + // This pointer cannot be used as an integer constant expression. + __asm__ __volatile__("\n#define GLOBAL_A abcd%0\n" : : "n"(&s.a)); // expected-error{{constraint 'n' expects an integer constant expression}} +}