diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -6036,6 +6036,7 @@ struct OffsetOfComponent { SourceLocation LocStart, LocEnd; bool isBrackets; // true if [expr], false if .ident + bool isQualifier; union { IdentifierInfo *IdentInfo; Expr *E; diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -2641,10 +2641,13 @@ // FIXME: This loop leaks the index expressions on error. while (true) { - if (Tok.is(tok::period)) { + if (Tok.is(tok::period) || Tok.is(tok::coloncolon)) { // offsetof-member-designator: offsetof-member-designator '.' identifier + if (Tok.is(tok::coloncolon)) + Comps.back().isQualifier = true; Comps.push_back(Sema::OffsetOfComponent()); Comps.back().isBrackets = false; + Comps.back().isQualifier = false; Comps.back().LocStart = ConsumeToken(); if (Tok.isNot(tok::identifier)) { @@ -2661,6 +2664,7 @@ // offsetof-member-designator: offsetof-member-design '[' expression ']' Comps.push_back(Sema::OffsetOfComponent()); Comps.back().isBrackets = true; + Comps.back().isQualifier = false; BalancedDelimiterTracker ST(*this, tok::l_square); ST.consumeOpen(); Comps.back().LocStart = ST.getOpenLocation(); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -16692,6 +16692,10 @@ if (!MemberDecl) { if ((IndirectMemberDecl = R.getAsSingle())) MemberDecl = IndirectMemberDecl->getAnonField(); + + IdentifierInfo *II = RD->getIdentifier(); + if (II == OC.U.IdentInfo && OC.isQualifier) + continue; } if (!MemberDecl) { diff --git a/clang/test/Sema/offsetof.c b/clang/test/Sema/offsetof.c --- a/clang/test/Sema/offsetof.c +++ b/clang/test/Sema/offsetof.c @@ -73,3 +73,8 @@ return __builtin_offsetof(Array, array[*(int*)0]); // expected-warning{{indirection of non-volatile null pointer}} expected-note{{__builtin_trap}} } +// https://github.com/llvm/llvm-project/issues/64154 +struct X2 { int a; }; +int x2[__builtin_offsetof(struct X2, X2::a) == 0 ? 1 : -1]; +int x3[__builtin_offsetof(struct X2, X2::X2) == 0 ? 1 : -1]; // expected-error{{no member named 'X2'}} +