diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -56,6 +56,7 @@ C++ Language Changes -------------------- +- Improved `__builtin_offsetof` support, allowing qualified name in member designator. C++20 Feature Support ^^^^^^^^^^^^^^^^^^^^^ 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 @@ -16663,6 +16663,9 @@ << CurrentType); RecordDecl *RD = RC->getDecl(); + if (OC.isQualifier && RD->getIdentifier() == OC.U.IdentInfo) + continue; + // C++ [lib.support.types]p5: // The macro offsetof accepts a restricted set of type arguments in this // International Standard. type shall be a POD structure or a POD union 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'}} + diff --git a/clang/test/SemaCXX/offsetof.cpp b/clang/test/SemaCXX/offsetof.cpp --- a/clang/test/SemaCXX/offsetof.cpp +++ b/clang/test/SemaCXX/offsetof.cpp @@ -98,3 +98,7 @@ B x; }, a); } + +// https://github.com/llvm/llvm-project/issues/64154 +struct X2 { int a; static int static_a; }; +int x2[__builtin_offsetof(struct X2, X2::static_a) == 0 ? 1 : -1]; // expected-error{{no member named 'static_a'}}