diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td --- a/clang/include/clang/Basic/DiagnosticCommonKinds.td +++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td @@ -279,6 +279,9 @@ def err_asm_invalid_type : Error< "invalid type %0 in asm %select{input|output}1">; + def err_ms_asm_bitfield_unsupported : Error< + "bit-fields are not supported as operands in inline asm blocks">; + def warn_stack_clash_protection_inline_asm : Warning< "Unable to protect inline asm that clobbers stack pointer against stack clash">, InGroup>; diff --git a/clang/lib/Sema/SemaStmtAsm.cpp b/clang/lib/Sema/SemaStmtAsm.cpp --- a/clang/lib/Sema/SemaStmtAsm.cpp +++ b/clang/lib/Sema/SemaStmtAsm.cpp @@ -932,13 +932,23 @@ bool IsSimple = (NumOutputs != 0 || NumInputs != 0); setFunctionHasBranchProtectedScope(); + bool InvalidOperand = false; for (uint64_t I = 0; I < NumOutputs + NumInputs; ++I) { - if (Exprs[I]->getType()->isBitIntType()) - return StmtError( - Diag(Exprs[I]->getBeginLoc(), diag::err_asm_invalid_type) + if (Exprs[I]->getType()->isBitIntType()) { + InvalidOperand = true; + Diag(Exprs[I]->getBeginLoc(), diag::err_asm_invalid_type) << Exprs[I]->getType() << (I < NumOutputs) - << Exprs[I]->getSourceRange()); + << Exprs[I]->getSourceRange(); + } else if (Exprs[I]->refersToBitField()) { + InvalidOperand = true; + FieldDecl *BitField = Exprs[I]->getSourceBitField(); + Diag(Exprs[I]->getBeginLoc(), diag::err_ms_asm_bitfield_unsupported) + << Exprs[I]->getSourceRange(); + Diag(BitField->getLocation(), diag::note_bitfield_decl); + } } + if (InvalidOperand) + return StmtError(); MSAsmStmt *NS = new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple, diff --git a/clang/test/Parser/ms-inline-asm.c b/clang/test/Parser/ms-inline-asm.c --- a/clang/test/Parser/ms-inline-asm.c +++ b/clang/test/Parser/ms-inline-asm.c @@ -62,6 +62,18 @@ __asm mov eax, offset A // expected-error {{offset operator cannot yet handle constants}} } +// GH57791 +typedef struct S { + unsigned bf1:1; // expected-note {{bit-field is declared here}} + unsigned bf2:1; // expected-note {{bit-field is declared here}} +} S; +void t15(S s) { + __asm { + mov eax, s.bf1 // expected-error {{bit-fields are not supported as operands in inline asm blocks}} + mov s.bf2, eax // expected-error {{bit-fields are not supported as operands in inline asm blocks}} + } +} + int t_fail(void) { // expected-note {{to match this}} __asm __asm { // expected-error 3 {{expected}} expected-note {{to match this}}