This is an archive of the discontinued LLVM Phabricator instance.

[clang] Fixes compile error that double colon operator cannot resolve macro with parentheses.
AcceptedPublic

Authored by lygstate on Aug 7 2023, 9:55 AM.

Details

Summary

Error message:

In file included from ../src/amd/addrlib/src/core/addrobject.h:21:
../src/amd/addrlib/src/core/addrcommon.h:343:13: error: expected unqualified-id
    out = ::_tzcnt_u32(mask);
            ^
/usr/lib/llvm-15/lib/clang/15.0.6/include/bmiintrin.h:74:27: note: expanded from macro '_tzcnt_u32'
#define _tzcnt_u32(a)     (__tzcnt_u32((a)))

This is because both GCC/Clang doesn't support compiling the following code:

#ifdef _MSC_VER
#include <intrin.h>
#else
#include <x86intrin.h>
#endif

int f(int a) {
    return ::(_tzcnt_u32)(a);
}

This is because the return statement expects an expression or braced init list: http://eel.is/c++draft/stmt.jump#general-1 but we really only need to care about the expression form (there's no braces in sight).
Grammatically, the leading :: will parse as a qualified-id because it matches the production for nested-name-specifier: http://eel.is/c++draft/expr.prim.id.qual#nt:qualified-id
That needs to be followed by an unqualified-id (http://eel.is/c++draft/expr.prim.id.unqual#nt:unqualified-id), but the open paren does not match any of the grammar productions, so this is a syntax error.

Closes: https://github.com/llvm/llvm-project/issues/64467

Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>

Diff Detail

Event Timeline

lygstate created this revision.Aug 7 2023, 9:55 AM
Herald added a project: Restricted Project. · View Herald TranscriptAug 7 2023, 9:55 AM
lygstate requested review of this revision.Aug 7 2023, 9:55 AM
Herald added a project: Restricted Project. · View Herald TranscriptAug 7 2023, 9:55 AM
Herald added a subscriber: cfe-commits. · View Herald Transcript
lygstate edited the summary of this revision. (Show Details)
lygstate edited the summary of this revision. (Show Details)
pengfei added a comment.EditedAug 8 2023, 6:27 PM

The description is not clear to me. You should describe the reason rather than phenomenon.

My understanding is double colon operator cannot resolve functions with parentheses. https://godbolt.org/z/6P47se9WW

But I didn't find enough proof in Google. It'd be more persuasive if you can find it and add to the description.

Would we be better off creating proper function definitions - we already have similar duplicates for _bextr_u64 (Intel) vs __bextr_u64 (AMD) names that do this

The description is not clear to me. You should describe the reason rather than phenomenon.

My understanding is double colon operator cannot resolve functions with parentheses. https://godbolt.org/z/6P47se9WW

error: expected unqualified-id

return ::_tzcnt_u32(a);
         ^

/opt/compiler-explorer/clang-16.0.0/lib/clang/16/include/bmiintrin.h:74:27: note: expanded from macro '_tzcnt_u32'
#define _tzcnt_u32(a) (__tzcnt_u32((a)))

Looks like double colon operator cannot resolve macros with parentheses, is that a compiler bug or we should handled it in code?

But I didn't find enough proof in Google. It'd be more persuasive if you can find it and add to the description.

The description is not clear to me. You should describe the reason rather than phenomenon.

My understanding is double colon operator cannot resolve functions with parentheses. https://godbolt.org/z/6P47se9WW

error: expected unqualified-id

return ::_tzcnt_u32(a);
         ^

/opt/compiler-explorer/clang-16.0.0/lib/clang/16/include/bmiintrin.h:74:27: note: expanded from macro '_tzcnt_u32'
#define _tzcnt_u32(a) (__tzcnt_u32((a)))

Looks like double colon operator cannot resolve macros with parentheses, is that a compiler bug or we should handled it in code?

But I didn't find enough proof in Google. It'd be more persuasive if you can find it and add to the description.

GCC doesn't resolve it either. https://godbolt.org/z/Prb4s5d6o. So it should not be a bug.

lygstate retitled this revision from [clang] Fixes compile error like error: expected unqualified-id for ::_tzcnt_u32(mask); to [clang] Fixes compile error that double colon operator cannot resolve macro with parentheses..Aug 15 2023, 11:31 AM
lygstate updated this revision to Diff 550413.Aug 15 2023, 11:34 AM

creating proper function definitions instead of macro define

I'd prefer macro to duplicated definitions. We have such precedents, e.g., https://github.com/llvm/llvm-project/blob/main/clang/lib/Headers/xmmintrin.h#L2994
Besides, you should update the summary as well.

lygstate added a comment.EditedAug 15 2023, 7:53 PM

I'd prefer macro to duplicated definitions. We have such precedents, e.g., https://github.com/llvm/llvm-project/blob/main/clang/lib/Headers/xmmintrin.h#L2994

Do you means revert to the first version?

Besides, you should update the summary as well.

I don't know what kind of summary you want, You can give me that so I can update it

I'd prefer macro to duplicated definitions. We have such precedents, e.g., https://github.com/llvm/llvm-project/blob/main/clang/lib/Headers/xmmintrin.h#L2994

Do you means revert to the first version?

Yes.

Besides, you should update the summary as well.

I don't know what kind of summary you want, I can give me that so I can update it

A reliable source about double colon operator cannot resolve function with parentheses in C++ is the best I expect, however I haven't find one so far.
Maybe a short description about the phenomenon on GCC/Clang is better than just giving error message. I don't have strong request for this.

lygstate updated this revision to Diff 550587.Aug 15 2023, 8:46 PM
lygstate edited the summary of this revision. (Show Details)

Revert to version 1

pengfei accepted this revision.Aug 15 2023, 10:16 PM

LGTM.

This revision is now accepted and ready to land.Aug 15 2023, 10:16 PM

BTW, maybe @aaron.ballman knows why we don't support such syntax in C++.

BTW, maybe @aaron.ballman knows why we don't support such syntax in C++.

The return statement expects an expression or braced init list: http://eel.is/c++draft/stmt.jump#general-1 but we really only need to care about the expression form (there's no braces in sight).
Grammatically, the leading :: will parse as a qualified-id because it matches the production for nested-name-specifier: http://eel.is/c++draft/expr.prim.id.qual#nt:qualified-id
That needs to be followed by an unqualified-id (http://eel.is/c++draft/expr.prim.id.unqual#nt:unqualified-id), but the open paren does not match any of the grammar productions, so this is a syntax error.

BTW, maybe @aaron.ballman knows why we don't support such syntax in C++.

The return statement expects an expression or braced init list: http://eel.is/c++draft/stmt.jump#general-1 but we really only need to care about the expression form (there's no braces in sight).
Grammatically, the leading :: will parse as a qualified-id because it matches the production for nested-name-specifier: http://eel.is/c++draft/expr.prim.id.qual#nt:qualified-id
That needs to be followed by an unqualified-id (http://eel.is/c++draft/expr.prim.id.unqual#nt:unqualified-id), but the open paren does not match any of the grammar productions, so this is a syntax error.

Thanks @aaron.ballman for the detailed explanation! I have learnt it. @lygstate maybe include Aaron's explanation in commit message?

lygstate edited the summary of this revision. (Show Details)Aug 16 2023, 7:17 PM

Thanks @aaron.ballman for the detailed explanation! I have learnt it. @lygstate maybe include Aaron's explanation in commit message?

The commit message is updated, is that ready for merge?