[PATCH] D77491: [Sema] Fix incompatible builtin redeclarations in non-global scope
John McCall via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Thu May 7 12:31:30 PDT 2020
rjmccall requested changes to this revision.
rjmccall added inline comments.
This revision now requires changes to proceed.
================
Comment at: clang/lib/Sema/SemaDecl.cpp:3759
unsigned BuiltinID;
- if (Old->isImplicit() && (BuiltinID = Old->getBuiltinID())) {
+ bool RevertedBuiltin{Old->getIdentifier()->hasRevertedBuiltin()};
+ if (Old->isImplicit() &&
----------------
The old code didn't check this eagerly. The `Old->isImplicit()` check is unlikely to fire; please make sure that we don't do any extra work unless it does.
================
Comment at: clang/lib/Sema/SemaDecl.cpp:3765
+ // Also warn if it's a redeclaration of a builtin redeclaration. We know if
+ // it is if the previous declaration is a reverted builtin.
+ if (RevertedBuiltin ||
----------------
`hasRevertedBuiltin()` is global state for the identifier, so this check isn't specifically checking anything about the previous declaration, it's checking whether the identifier was ever used for a builtin. Now, the implicit-ness of the previous declaration *is* declaration-specific, and there are very few ways that we end up with an implicit function declaration. It's quite possible that implicit + identifier-is-or-was-a-builtin is sufficient to say that it's an implicit builtin declaration today. However, I do worry about the fact that this change is losing the is-predefined-library-function part of the existing check, and I think we should continue to check that somehow. If that means changing how we revert builtin-ness, e.g. by continuing to store the old builtinID but just recording that it's been reverted, that seems reasonable.
That said, I think there's a larger problem, which is that you're ignoring half of the point of the comment you've deleted:
> // Doing this for local extern declarations is problematic. If
> // the builtin declaration remains visible, a second invalid
> // local declaration will produce a hard error; if it doesn't
> // remain visible, a single bogus local redeclaration (which is
> // actually only a warning) could break all the downstream code.
The problem with reverting the builtin-ness of the identifier after seeing a bad local declaration is that, after we leave the scope of that function, the global function doesn't go back to being a builtin, which can break the behavior of all the rest of the code.
If we want to handle this kind of bogus local declaration correctly, I think we need to stop relying primarily on the builtin-ness of the identifier — which is global state and therefore inherently problematic — and instead start recording whether a specific declaration has builtin semantics. The most obvious way to do that is to record an implicit `BuiltinAttr` when implicitly declaring a builtin, inherit that attribute only on compatible redeclarations, and then make builtin queries look for that attribute instead of checking the identifier.
Richard, do you agree?
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D77491/new/
https://reviews.llvm.org/D77491
More information about the cfe-commits
mailing list