aaron.ballman created this revision.
aaron.ballman added reviewers: rsmith, comex, erichkeane, jyknight, rjmccall.
Herald added a project: All.
aaron.ballman requested review of this revision.
Herald added a project: clang.
Currently, Clang handles some qualifiers correctly for `__auto_type`, but it
does not handle the `restrict` or `_Atomic` qualifiers in the same way that GCC
does. This patch handles those qualifiers so that they attach to the deduced
type the same as `const` and `volatile` already do.
This fixes https://github.com/llvm/llvm-project/issues/53652
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D122029
Files:
clang/docs/ReleaseNotes.rst
clang/lib/AST/ASTContext.cpp
clang/lib/Sema/SemaExpr.cpp
clang/lib/Sema/SemaType.cpp
clang/test/Sema/auto-type.c
Index: clang/test/Sema/auto-type.c
===================================================================
--- clang/test/Sema/auto-type.c
+++ clang/test/Sema/auto-type.c
@@ -24,3 +24,39 @@
int k(l)
__auto_type l; // expected-error {{'__auto_type' not allowed in K&R-style function parameter}}
{}
+
+void Issue53652(void) {
+ // Ensure that qualifiers all work the same way as GCC.
+ const __auto_type cat = a;
+ const __auto_type pcat = &a;
+ volatile __auto_type vat = a;
+ volatile __auto_type pvat = &a;
+ restrict __auto_type rat = &a;
+ _Atomic __auto_type aat1 = a;
+ _Atomic __auto_type paat = &a;
+
+ // GCC does not accept this either, for the same reason.
+ _Atomic(__auto_type) aat2 = a; // expected-error {{'__auto_type' not allowed here}} \
+ // expected-warning {{type specifier missing, defaults to 'int'}}
+
+ // Ensure the types are what we expect them to be.
+ _Static_assert(__builtin_types_compatible_p(__typeof(cat), const int), "");
+ _Static_assert(__builtin_types_compatible_p(__typeof(pcat), int *const), "");
+ _Static_assert(__builtin_types_compatible_p(__typeof(vat), volatile int), "");
+ _Static_assert(__builtin_types_compatible_p(__typeof(pvat), int *volatile), "");
+ _Static_assert(__builtin_types_compatible_p(__typeof(rat), int *restrict), "");
+ _Static_assert(__builtin_types_compatible_p(__typeof(aat1), _Atomic int), "");
+ _Static_assert(__builtin_types_compatible_p(__typeof(paat), _Atomic(int *)), "");
+
+ // Ensure the types also work in generic selection expressions. Remember, the
+ // type of the expression argument to _Generic is treated as-if it undergoes
+ // lvalue to rvalue conversion, which drops qualifiers. We're making sure the
+ // use of __auto_type doesn't impact that.
+ (void)_Generic(cat, int : 0);
+ (void)_Generic(pcat, int * : 0);
+ (void)_Generic(vat, int : 0);
+ (void)_Generic(pvat, int * : 0);
+ (void)_Generic(rat, int * : 0);
+ (void)_Generic(aat1, int : 0);
+ (void)_Generic(paat, int * : 0);
+}
Index: clang/lib/Sema/SemaType.cpp
===================================================================
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -1880,6 +1880,14 @@
return "type name";
}
+static bool isDependentOrGNUAutoType(QualType T) {
+ if (T->isDependentType())
+ return true;
+
+ const auto *AT = dyn_cast<AutoType>(T);
+ return AT && AT->getKeyword() == AutoTypeKeyword::GNUAutoType;
+}
+
QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc,
Qualifiers Qs, const DeclSpec *DS) {
if (T.isNull())
@@ -1913,9 +1921,15 @@
DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee;
ProblemTy = EltTy;
}
- } else if (!T->isDependentType()) {
- DiagID = diag::err_typecheck_invalid_restrict_not_pointer;
- ProblemTy = T;
+ } else if (!isDependentOrGNUAutoType(T)) {
+ // For an __auto_type variable, we may not have seen the initializer yet
+ // and so have no idea whether the underlying type is a pointer type or
+ // not.
+ const auto *AT = dyn_cast<AutoType>(T);
+ if (!AT || AT->getKeyword() != AutoTypeKeyword::GNUAutoType) {
+ DiagID = diag::err_typecheck_invalid_restrict_not_pointer;
+ ProblemTy = T;
+ }
}
if (DiagID) {
@@ -9101,7 +9115,7 @@
}
QualType Sema::BuildAtomicType(QualType T, SourceLocation Loc) {
- if (!T->isDependentType()) {
+ if (!isDependentOrGNUAutoType(T)) {
// FIXME: It isn't entirely clear whether incomplete atomic types
// are allowed or not; for simplicity, ban them for the moment.
if (RequireCompleteType(Loc, T, diag::err_atomic_specifier_bad_type, 0))
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -9399,6 +9399,15 @@
return Compatible;
}
+ // If the LHS has an __auto_type, there are no additional type constraints
+ // to be worried about.
+ if (const auto *AT = dyn_cast<AutoType>(LHSType)) {
+ if (AT->getKeyword() == AutoTypeKeyword::GNUAutoType) {
+ Kind = CK_NoOp;
+ return Compatible;
+ }
+ }
+
// If we have an atomic type, try a non-atomic assignment, then just add an
// atomic qualification step.
if (const AtomicType *AtomicTy = dyn_cast<AtomicType>(LHSType)) {
Index: clang/lib/AST/ASTContext.cpp
===================================================================
--- clang/lib/AST/ASTContext.cpp
+++ clang/lib/AST/ASTContext.cpp
@@ -10285,7 +10285,16 @@
if (RHS->isObjCIdType() && LHS->isBlockPointerType())
return RHS;
}
-
+ // Allow __auto_type to match anything; it merges to the type with more
+ // information.
+ if (const auto *AT = LHS->getAs<AutoType>()) {
+ if (AT->getKeyword() == AutoTypeKeyword::GNUAutoType)
+ return RHS;
+ }
+ if (const auto *AT = LHS->getAs<AutoType>()) {
+ if (AT->getKeyword() == AutoTypeKeyword::GNUAutoType)
+ return RHS;
+ }
return {};
}
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -62,6 +62,11 @@
either return ``None`` or a ``llvm::Optional`` wrapping a valid ``Expr*``.
This fixes `Issue 53742 <https://github.com/llvm/llvm-project/issues/53742>`_.
+- Now allow the `restrict` and `_Atomic` qualifiers to be used in conjunction
+ with `__auto_type` to match the behavior in GCC. This fixes
+ `Issue 53652 <https://github.com/llvm/llvm-project/issues/53652>`_.
+
+
Improvements to Clang's diagnostics
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- ``-Wliteral-range`` will warn on floating-point equality comparisons with
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits