[clang] [Clang] [C23] Fix typeof_unqual for qualified array types (PR #92767)
https://github.com/AaronBallman approved this pull request. LGTM thank you! https://github.com/llvm/llvm-project/pull/92767 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] [C23] Fix typeof_unqual for qualified array types (PR #92767)
@@ -92,3 +92,43 @@ extern __attribute__((address_space(0))) int type_attr_test_2; // expec void invalid_param_fn(__attribute__((address_space(1))) int i); // expected-error {{parameter may not be qualified with an address space}} typeof(invalid_param_fn) invalid_param_1; typeof_unqual(invalid_param_fn) invalid_param_2; + +// Ensure restrict is stripped +extern int *restrict p1; +extern int *p2; +extern typeof(p1) p1; +extern typeof_unqual(p1) p2; + +// Ensure array qualifications are removed +extern const int aci[2]; +extern const int acii[2][2]; +extern int ai[2]; +extern int aii[2][2]; +extern typeof(aci) aci; +extern typeof_unqual(aci) ai; +extern typeof(acii) acii; +extern typeof_unqual(acii) aii; + +extern int *restrict arpi[2]; +extern int *restrict arpii[2][2]; +extern int *api[2]; +extern int *apii[2][2]; +extern typeof(arpi) arpi; +extern typeof_unqual(arpi) api; +extern typeof(arpii) arpii; +extern typeof_unqual(arpii) apii; + +extern int _Atomic aAi[2]; +extern int _Atomic aAii[2][2]; +extern typeof(aAi) aAi; +extern typeof_unqual(aAi) ai; +extern typeof(aAii) aAii; +extern typeof_unqual(aAii) aii; AaronBallman wrote: Ah, so yeah, I think I was confused above. Both `typeof(_Atomic(int)[2][2])` and `typeof(_Atomit int[2][2])` would return a two-dimensional array of atomic-qualified ints, and `typeof_unqual` is defined to return the non-atomic, unqualified version of the type that would come out of `typeof`, so that would mean both forms come out of `typeof_unqual` the same. https://github.com/llvm/llvm-project/pull/92767 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] [C23] Fix typeof_unqual for qualified array types (PR #92767)
https://github.com/MitalAshok updated https://github.com/llvm/llvm-project/pull/92767 >From f87cb4c754a477515746e2ac2f8906b93ccd1fe3 Mon Sep 17 00:00:00 2001 From: Mital Ashok Date: Mon, 20 May 2024 15:58:58 +0100 Subject: [PATCH 1/4] [Clang] [C23] Fix typeof_unqual for qualified array types Properly remove qualifiers for both the element type and the array type Fixes #92667 --- clang/include/clang/AST/ASTContext.h | 6 - clang/include/clang/AST/Type.h | 37 +-- clang/lib/AST/ASTContext.cpp | 14 +- clang/lib/AST/Type.cpp | 38 ++-- clang/test/Sema/c2x-typeof.c | 25 ++ 5 files changed, 84 insertions(+), 36 deletions(-) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index e03b112194786..ff7bdb7e7e1a6 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -2611,7 +2611,11 @@ class ASTContext : public RefCountedBase { /// /// \returns if this is an array type, the completely unqualified array type /// that corresponds to it. Otherwise, returns T.getUnqualifiedType(). - QualType getUnqualifiedArrayType(QualType T, Qualifiers ); + QualType getUnqualifiedArrayType(QualType T, Qualifiers ) const; + QualType getUnqualifiedArrayType(QualType T) const { +Qualifiers Quals; +return getUnqualifiedArrayType(T, Quals); + } /// Determine whether the given types are equivalent after /// cvr-qualifiers have been removed. diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index da3834f19ca04..df7f396bae095 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -1605,6 +1605,10 @@ class QualType { QualType stripObjCKindOfType(const ASTContext ) const; /// Remove all qualifiers including _Atomic. + /// + /// Like getUnqualifiedType(), the type may still be qualified if it is a + /// sugared array type. To strip qualifiers even from within a sugared array + /// type, use ASTContext::getUnqualifiedArrayType. QualType getAtomicUnqualifiedType() const; private: @@ -2092,8 +2096,8 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase { LLVM_PREFERRED_TYPE(TypeBitfields) unsigned : NumTypeBits; -LLVM_PREFERRED_TYPE(bool) -unsigned IsUnqual : 1; // If true: typeof_unqual, else: typeof +LLVM_PREFERRED_TYPE(TypeOfKind) +unsigned Kind : 1; }; class UsingBitfields { @@ -5273,19 +5277,20 @@ class MacroQualifiedType : public Type { /// extension) or a `typeof_unqual` expression (a C23 feature). class TypeOfExprType : public Type { Expr *TOExpr; + const ASTContext protected: friend class ASTContext; // ASTContext creates these. - TypeOfExprType(Expr *E, TypeOfKind Kind, QualType Can = QualType()); + TypeOfExprType(const ASTContext , Expr *E, TypeOfKind Kind, + QualType Can = QualType()); public: Expr *getUnderlyingExpr() const { return TOExpr; } /// Returns the kind of 'typeof' type this is. TypeOfKind getKind() const { -return TypeOfBits.IsUnqual ? TypeOfKind::Unqualified - : TypeOfKind::Qualified; +return static_cast(TypeOfBits.Kind); } /// Remove a single level of sugar. @@ -5306,7 +5311,8 @@ class TypeOfExprType : public Type { class DependentTypeOfExprType : public TypeOfExprType, public llvm::FoldingSetNode { public: - DependentTypeOfExprType(Expr *E, TypeOfKind Kind) : TypeOfExprType(E, Kind) {} + DependentTypeOfExprType(const ASTContext , Expr *E, TypeOfKind Kind) + : TypeOfExprType(Context, E, Kind) {} void Profile(llvm::FoldingSetNodeID , const ASTContext ) { Profile(ID, Context, getUnderlyingExpr(), @@ -5323,32 +5329,23 @@ class TypeOfType : public Type { friend class ASTContext; // ASTContext creates these. QualType TOType; + const ASTContext - TypeOfType(QualType T, QualType Can, TypeOfKind Kind) - : Type(TypeOf, - Kind == TypeOfKind::Unqualified ? Can.getAtomicUnqualifiedType() - : Can, - T->getDependence()), -TOType(T) { -TypeOfBits.IsUnqual = Kind == TypeOfKind::Unqualified; - } + TypeOfType(const ASTContext , QualType T, QualType Can, + TypeOfKind Kind); public: QualType getUnmodifiedType() const { return TOType; } /// Remove a single level of sugar. - QualType desugar() const { -QualType QT = getUnmodifiedType(); -return TypeOfBits.IsUnqual ? QT.getAtomicUnqualifiedType() : QT; - } + QualType desugar() const; /// Returns whether this type directly provides sugar. bool isSugared() const { return true; } /// Returns the kind of 'typeof' type this is. TypeOfKind getKind() const { -return TypeOfBits.IsUnqual ? TypeOfKind::Unqualified - :
[clang] [Clang] [C23] Fix typeof_unqual for qualified array types (PR #92767)
@@ -92,3 +92,43 @@ extern __attribute__((address_space(0))) int type_attr_test_2; // expec void invalid_param_fn(__attribute__((address_space(1))) int i); // expected-error {{parameter may not be qualified with an address space}} typeof(invalid_param_fn) invalid_param_1; typeof_unqual(invalid_param_fn) invalid_param_2; + +// Ensure restrict is stripped +extern int *restrict p1; +extern int *p2; +extern typeof(p1) p1; +extern typeof_unqual(p1) p2; + +// Ensure array qualifications are removed +extern const int aci[2]; +extern const int acii[2][2]; +extern int ai[2]; +extern int aii[2][2]; +extern typeof(aci) aci; +extern typeof_unqual(aci) ai; +extern typeof(acii) acii; +extern typeof_unqual(acii) aii; + +extern int *restrict arpi[2]; +extern int *restrict arpii[2][2]; +extern int *api[2]; +extern int *apii[2][2]; +extern typeof(arpi) arpi; +extern typeof_unqual(arpi) api; +extern typeof(arpii) arpii; +extern typeof_unqual(arpii) apii; + +extern int _Atomic aAi[2]; +extern int _Atomic aAii[2][2]; +extern typeof(aAi) aAi; +extern typeof_unqual(aAi) ai; +extern typeof(aAii) aAii; +extern typeof_unqual(aAii) aii; MitalAshok wrote: I don't think this is the correct behaviour now. `_Atomic(int) x[2][2]` and `int _Atomic y[2][2]` have the same type, and `typeof_unqual(int _Atomic[2][2])` and `typeof_unqual(_Atomic(int)[2][2])` should return the same type unchanged because, as you've said, the array isn't `_Atomic` qualified (and arrays cant be `_Atomic` in C). So I'll probably have to remove `Context::getAtomicUnqualifiedArrayType` and replace it with `Context.getUnqualifiedArrayType(Can.getAtomicUnqualifiedType())` https://github.com/llvm/llvm-project/pull/92767 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] [C23] Fix typeof_unqual for qualified array types (PR #92767)
@@ -92,3 +92,43 @@ extern __attribute__((address_space(0))) int type_attr_test_2; // expec void invalid_param_fn(__attribute__((address_space(1))) int i); // expected-error {{parameter may not be qualified with an address space}} typeof(invalid_param_fn) invalid_param_1; typeof_unqual(invalid_param_fn) invalid_param_2; + +// Ensure restrict is stripped +extern int *restrict p1; +extern int *p2; +extern typeof(p1) p1; +extern typeof_unqual(p1) p2; + +// Ensure array qualifications are removed +extern const int aci[2]; +extern const int acii[2][2]; +extern int ai[2]; +extern int aii[2][2]; +extern typeof(aci) aci; +extern typeof_unqual(aci) ai; +extern typeof(acii) acii; +extern typeof_unqual(acii) aii; MitalAshok wrote: Yeah, there's a GCC bug for this already: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112841 https://github.com/llvm/llvm-project/pull/92767 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] [C23] Fix typeof_unqual for qualified array types (PR #92767)
@@ -92,3 +92,43 @@ extern __attribute__((address_space(0))) int type_attr_test_2; // expec void invalid_param_fn(__attribute__((address_space(1))) int i); // expected-error {{parameter may not be qualified with an address space}} typeof(invalid_param_fn) invalid_param_1; typeof_unqual(invalid_param_fn) invalid_param_2; + +// Ensure restrict is stripped +extern int *restrict p1; +extern int *p2; +extern typeof(p1) p1; +extern typeof_unqual(p1) p2; + +// Ensure array qualifications are removed +extern const int aci[2]; +extern const int acii[2][2]; +extern int ai[2]; +extern int aii[2][2]; +extern typeof(aci) aci; +extern typeof_unqual(aci) ai; +extern typeof(acii) acii; +extern typeof_unqual(acii) aii; + +extern int *restrict arpi[2]; +extern int *restrict arpii[2][2]; +extern int *api[2]; +extern int *apii[2][2]; +extern typeof(arpi) arpi; +extern typeof_unqual(arpi) api; +extern typeof(arpii) arpii; +extern typeof_unqual(arpii) apii; + +extern int _Atomic aAi[2]; +extern int _Atomic aAii[2][2]; +extern typeof(aAi) aAi; +extern typeof_unqual(aAi) ai; +extern typeof(aAii) aAii; +extern typeof_unqual(aAii) aii; AaronBallman wrote: I think this is a more complicated situation, perhaps. `_Atomic` as a type qualifier (as with `_Atomic type`) is excluded in terms of arrays and elements being identically qualified (see footnote 42, which says "This does not apply to the _Atomic qualifier.") so the array is not atomic to begin with. So `typeof_unqual` would strip the non-existent qualifiers from the array in this case but leave them alone in the element type. However, `_Atomic` as a type specifier (as with `_Atomic(type)`) is an atomic-qualified type and so it would be stripped in that case (see footnote 146 which also reminds us that `_Atomic(type-name)` is an atomic-qualified type). So I think the behavior of this case is correct but we need another test for `_Atomic(int)`. https://github.com/llvm/llvm-project/pull/92767 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] [C23] Fix typeof_unqual for qualified array types (PR #92767)
@@ -92,3 +92,43 @@ extern __attribute__((address_space(0))) int type_attr_test_2; // expec void invalid_param_fn(__attribute__((address_space(1))) int i); // expected-error {{parameter may not be qualified with an address space}} typeof(invalid_param_fn) invalid_param_1; typeof_unqual(invalid_param_fn) invalid_param_2; + +// Ensure restrict is stripped +extern int *restrict p1; +extern int *p2; +extern typeof(p1) p1; +extern typeof_unqual(p1) p2; + +// Ensure array qualifications are removed +extern const int aci[2]; +extern const int acii[2][2]; +extern int ai[2]; +extern int aii[2][2]; +extern typeof(aci) aci; +extern typeof_unqual(aci) ai; +extern typeof(acii) acii; +extern typeof_unqual(acii) aii; + +extern int *restrict arpi[2]; +extern int *restrict arpii[2][2]; +extern int *api[2]; +extern int *apii[2][2]; +extern typeof(arpi) arpi; +extern typeof_unqual(arpi) api; +extern typeof(arpii) arpii; +extern typeof_unqual(arpii) apii; AaronBallman wrote: GCC also disagrees on these `typeof_unqual`s, but I think that behavior is also incorrect for the same reason as above. https://github.com/llvm/llvm-project/pull/92767 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] [C23] Fix typeof_unqual for qualified array types (PR #92767)
@@ -92,3 +92,43 @@ extern __attribute__((address_space(0))) int type_attr_test_2; // expec void invalid_param_fn(__attribute__((address_space(1))) int i); // expected-error {{parameter may not be qualified with an address space}} typeof(invalid_param_fn) invalid_param_1; typeof_unqual(invalid_param_fn) invalid_param_2; + +// Ensure restrict is stripped +extern int *restrict p1; +extern int *p2; +extern typeof(p1) p1; +extern typeof_unqual(p1) p2; + +// Ensure array qualifications are removed +extern const int aci[2]; +extern const int acii[2][2]; +extern int ai[2]; +extern int aii[2][2]; +extern typeof(aci) aci; +extern typeof_unqual(aci) ai; +extern typeof(acii) acii; +extern typeof_unqual(acii) aii; AaronBallman wrote: Curiously, this is different from the results in GCC: https://godbolt.org/z/5rczxdGKn Based on my understanding of "An array and its element type are always considered to be identically qualified.", I think GCC's behavior is incorrect, but it would be good to file an issue with them to let them know to ensure we agree. https://github.com/llvm/llvm-project/pull/92767 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] [C23] Fix typeof_unqual for qualified array types (PR #92767)
https://github.com/AaronBallman edited https://github.com/llvm/llvm-project/pull/92767 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] [C23] Fix typeof_unqual for qualified array types (PR #92767)
https://github.com/AaronBallman approved this pull request. LGTM! Precommit CI failure is unrelated to your changes. https://github.com/llvm/llvm-project/pull/92767 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] [C23] Fix typeof_unqual for qualified array types (PR #92767)
https://github.com/MitalAshok updated https://github.com/llvm/llvm-project/pull/92767 >From f87cb4c754a477515746e2ac2f8906b93ccd1fe3 Mon Sep 17 00:00:00 2001 From: Mital Ashok Date: Mon, 20 May 2024 15:58:58 +0100 Subject: [PATCH 1/4] [Clang] [C23] Fix typeof_unqual for qualified array types Properly remove qualifiers for both the element type and the array type Fixes #92667 --- clang/include/clang/AST/ASTContext.h | 6 - clang/include/clang/AST/Type.h | 37 +-- clang/lib/AST/ASTContext.cpp | 14 +- clang/lib/AST/Type.cpp | 38 ++-- clang/test/Sema/c2x-typeof.c | 25 ++ 5 files changed, 84 insertions(+), 36 deletions(-) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index e03b112194786..ff7bdb7e7e1a6 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -2611,7 +2611,11 @@ class ASTContext : public RefCountedBase { /// /// \returns if this is an array type, the completely unqualified array type /// that corresponds to it. Otherwise, returns T.getUnqualifiedType(). - QualType getUnqualifiedArrayType(QualType T, Qualifiers ); + QualType getUnqualifiedArrayType(QualType T, Qualifiers ) const; + QualType getUnqualifiedArrayType(QualType T) const { +Qualifiers Quals; +return getUnqualifiedArrayType(T, Quals); + } /// Determine whether the given types are equivalent after /// cvr-qualifiers have been removed. diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index da3834f19ca04..df7f396bae095 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -1605,6 +1605,10 @@ class QualType { QualType stripObjCKindOfType(const ASTContext ) const; /// Remove all qualifiers including _Atomic. + /// + /// Like getUnqualifiedType(), the type may still be qualified if it is a + /// sugared array type. To strip qualifiers even from within a sugared array + /// type, use ASTContext::getUnqualifiedArrayType. QualType getAtomicUnqualifiedType() const; private: @@ -2092,8 +2096,8 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase { LLVM_PREFERRED_TYPE(TypeBitfields) unsigned : NumTypeBits; -LLVM_PREFERRED_TYPE(bool) -unsigned IsUnqual : 1; // If true: typeof_unqual, else: typeof +LLVM_PREFERRED_TYPE(TypeOfKind) +unsigned Kind : 1; }; class UsingBitfields { @@ -5273,19 +5277,20 @@ class MacroQualifiedType : public Type { /// extension) or a `typeof_unqual` expression (a C23 feature). class TypeOfExprType : public Type { Expr *TOExpr; + const ASTContext protected: friend class ASTContext; // ASTContext creates these. - TypeOfExprType(Expr *E, TypeOfKind Kind, QualType Can = QualType()); + TypeOfExprType(const ASTContext , Expr *E, TypeOfKind Kind, + QualType Can = QualType()); public: Expr *getUnderlyingExpr() const { return TOExpr; } /// Returns the kind of 'typeof' type this is. TypeOfKind getKind() const { -return TypeOfBits.IsUnqual ? TypeOfKind::Unqualified - : TypeOfKind::Qualified; +return static_cast(TypeOfBits.Kind); } /// Remove a single level of sugar. @@ -5306,7 +5311,8 @@ class TypeOfExprType : public Type { class DependentTypeOfExprType : public TypeOfExprType, public llvm::FoldingSetNode { public: - DependentTypeOfExprType(Expr *E, TypeOfKind Kind) : TypeOfExprType(E, Kind) {} + DependentTypeOfExprType(const ASTContext , Expr *E, TypeOfKind Kind) + : TypeOfExprType(Context, E, Kind) {} void Profile(llvm::FoldingSetNodeID , const ASTContext ) { Profile(ID, Context, getUnderlyingExpr(), @@ -5323,32 +5329,23 @@ class TypeOfType : public Type { friend class ASTContext; // ASTContext creates these. QualType TOType; + const ASTContext - TypeOfType(QualType T, QualType Can, TypeOfKind Kind) - : Type(TypeOf, - Kind == TypeOfKind::Unqualified ? Can.getAtomicUnqualifiedType() - : Can, - T->getDependence()), -TOType(T) { -TypeOfBits.IsUnqual = Kind == TypeOfKind::Unqualified; - } + TypeOfType(const ASTContext , QualType T, QualType Can, + TypeOfKind Kind); public: QualType getUnmodifiedType() const { return TOType; } /// Remove a single level of sugar. - QualType desugar() const { -QualType QT = getUnmodifiedType(); -return TypeOfBits.IsUnqual ? QT.getAtomicUnqualifiedType() : QT; - } + QualType desugar() const; /// Returns whether this type directly provides sugar. bool isSugared() const { return true; } /// Returns the kind of 'typeof' type this is. TypeOfKind getKind() const { -return TypeOfBits.IsUnqual ? TypeOfKind::Unqualified - :
[clang] [Clang] [C23] Fix typeof_unqual for qualified array types (PR #92767)
https://github.com/AaronBallman commented: The changes generally LG, but there's a merge conflict preventing the PR from going through precommit CI. https://github.com/llvm/llvm-project/pull/92767 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] [C23] Fix typeof_unqual for qualified array types (PR #92767)
@@ -2092,8 +2096,8 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase { LLVM_PREFERRED_TYPE(TypeBitfields) unsigned : NumTypeBits; -LLVM_PREFERRED_TYPE(bool) -unsigned IsUnqual : 1; // If true: typeof_unqual, else: typeof +LLVM_PREFERRED_TYPE(TypeOfKind) AaronBallman wrote: Good drive-by catch! Technically unrelated to this PR, but I think it's fine to leave in. https://github.com/llvm/llvm-project/pull/92767 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] [C23] Fix typeof_unqual for qualified array types (PR #92767)
https://github.com/AaronBallman edited https://github.com/llvm/llvm-project/pull/92767 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] [C23] Fix typeof_unqual for qualified array types (PR #92767)
@@ -92,3 +92,35 @@ extern __attribute__((address_space(0))) int type_attr_test_2; // expec void invalid_param_fn(__attribute__((address_space(1))) int i); // expected-error {{parameter may not be qualified with an address space}} typeof(invalid_param_fn) invalid_param_1; typeof_unqual(invalid_param_fn) invalid_param_2; + +// Ensure restrict is stripped +extern int *restrict p1; +extern int *p2; +extern typeof(p1) p1; +extern typeof_unqual(p1) p2; + +// Ensure array qualifications are removed +extern const int aci[2]; +extern const int acii[2][2]; +extern int ai[2]; +extern int aii[2][2]; +extern typeof(aci) aci; +extern typeof_unqual(aci) ai; +extern typeof(acii) acii; +extern typeof_unqual(acii) aii; + +extern int *restrict arpi[2]; +extern int *restrict arpii[2][2]; +extern int *api[2]; +extern int *apii[2][2]; +extern typeof(arpi) arpi; +extern typeof_unqual(arpi) api; +extern typeof(arpii) arpii; +extern typeof_unqual(arpii) apii; + +extern int _Atomic aAi[2]; +extern int _Atomic aAii[2][2]; +extern typeof(aAi) aAi; +extern typeof_unqual(aAi) ai; +extern typeof(aAii) aAii; +extern typeof_unqual(aAii) aii; AaronBallman wrote: [Re: line 127] Can you also add a test case like the one from #92667?See this comment inline on https://app.graphite.dev/github/pr/llvm/llvm-project/92767?utm_source=unchanged-line-comment;>Graphite. https://github.com/llvm/llvm-project/pull/92767 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] [C23] Fix typeof_unqual for qualified array types (PR #92767)
https://github.com/MitalAshok updated https://github.com/llvm/llvm-project/pull/92767 >From f87cb4c754a477515746e2ac2f8906b93ccd1fe3 Mon Sep 17 00:00:00 2001 From: Mital Ashok Date: Mon, 20 May 2024 15:58:58 +0100 Subject: [PATCH 1/3] [Clang] [C23] Fix typeof_unqual for qualified array types Properly remove qualifiers for both the element type and the array type Fixes #92667 --- clang/include/clang/AST/ASTContext.h | 6 - clang/include/clang/AST/Type.h | 37 +-- clang/lib/AST/ASTContext.cpp | 14 +- clang/lib/AST/Type.cpp | 38 ++-- clang/test/Sema/c2x-typeof.c | 25 ++ 5 files changed, 84 insertions(+), 36 deletions(-) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index e03b112194786..ff7bdb7e7e1a6 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -2611,7 +2611,11 @@ class ASTContext : public RefCountedBase { /// /// \returns if this is an array type, the completely unqualified array type /// that corresponds to it. Otherwise, returns T.getUnqualifiedType(). - QualType getUnqualifiedArrayType(QualType T, Qualifiers ); + QualType getUnqualifiedArrayType(QualType T, Qualifiers ) const; + QualType getUnqualifiedArrayType(QualType T) const { +Qualifiers Quals; +return getUnqualifiedArrayType(T, Quals); + } /// Determine whether the given types are equivalent after /// cvr-qualifiers have been removed. diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index da3834f19ca04..df7f396bae095 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -1605,6 +1605,10 @@ class QualType { QualType stripObjCKindOfType(const ASTContext ) const; /// Remove all qualifiers including _Atomic. + /// + /// Like getUnqualifiedType(), the type may still be qualified if it is a + /// sugared array type. To strip qualifiers even from within a sugared array + /// type, use ASTContext::getUnqualifiedArrayType. QualType getAtomicUnqualifiedType() const; private: @@ -2092,8 +2096,8 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase { LLVM_PREFERRED_TYPE(TypeBitfields) unsigned : NumTypeBits; -LLVM_PREFERRED_TYPE(bool) -unsigned IsUnqual : 1; // If true: typeof_unqual, else: typeof +LLVM_PREFERRED_TYPE(TypeOfKind) +unsigned Kind : 1; }; class UsingBitfields { @@ -5273,19 +5277,20 @@ class MacroQualifiedType : public Type { /// extension) or a `typeof_unqual` expression (a C23 feature). class TypeOfExprType : public Type { Expr *TOExpr; + const ASTContext protected: friend class ASTContext; // ASTContext creates these. - TypeOfExprType(Expr *E, TypeOfKind Kind, QualType Can = QualType()); + TypeOfExprType(const ASTContext , Expr *E, TypeOfKind Kind, + QualType Can = QualType()); public: Expr *getUnderlyingExpr() const { return TOExpr; } /// Returns the kind of 'typeof' type this is. TypeOfKind getKind() const { -return TypeOfBits.IsUnqual ? TypeOfKind::Unqualified - : TypeOfKind::Qualified; +return static_cast(TypeOfBits.Kind); } /// Remove a single level of sugar. @@ -5306,7 +5311,8 @@ class TypeOfExprType : public Type { class DependentTypeOfExprType : public TypeOfExprType, public llvm::FoldingSetNode { public: - DependentTypeOfExprType(Expr *E, TypeOfKind Kind) : TypeOfExprType(E, Kind) {} + DependentTypeOfExprType(const ASTContext , Expr *E, TypeOfKind Kind) + : TypeOfExprType(Context, E, Kind) {} void Profile(llvm::FoldingSetNodeID , const ASTContext ) { Profile(ID, Context, getUnderlyingExpr(), @@ -5323,32 +5329,23 @@ class TypeOfType : public Type { friend class ASTContext; // ASTContext creates these. QualType TOType; + const ASTContext - TypeOfType(QualType T, QualType Can, TypeOfKind Kind) - : Type(TypeOf, - Kind == TypeOfKind::Unqualified ? Can.getAtomicUnqualifiedType() - : Can, - T->getDependence()), -TOType(T) { -TypeOfBits.IsUnqual = Kind == TypeOfKind::Unqualified; - } + TypeOfType(const ASTContext , QualType T, QualType Can, + TypeOfKind Kind); public: QualType getUnmodifiedType() const { return TOType; } /// Remove a single level of sugar. - QualType desugar() const { -QualType QT = getUnmodifiedType(); -return TypeOfBits.IsUnqual ? QT.getAtomicUnqualifiedType() : QT; - } + QualType desugar() const; /// Returns whether this type directly provides sugar. bool isSugared() const { return true; } /// Returns the kind of 'typeof' type this is. TypeOfKind getKind() const { -return TypeOfBits.IsUnqual ? TypeOfKind::Unqualified - :
[clang] [Clang] [C23] Fix typeof_unqual for qualified array types (PR #92767)
https://github.com/MitalAshok updated https://github.com/llvm/llvm-project/pull/92767 >From f87cb4c754a477515746e2ac2f8906b93ccd1fe3 Mon Sep 17 00:00:00 2001 From: Mital Ashok Date: Mon, 20 May 2024 15:58:58 +0100 Subject: [PATCH 1/2] [Clang] [C23] Fix typeof_unqual for qualified array types Properly remove qualifiers for both the element type and the array type Fixes #92667 --- clang/include/clang/AST/ASTContext.h | 6 - clang/include/clang/AST/Type.h | 37 +-- clang/lib/AST/ASTContext.cpp | 14 +- clang/lib/AST/Type.cpp | 38 ++-- clang/test/Sema/c2x-typeof.c | 25 ++ 5 files changed, 84 insertions(+), 36 deletions(-) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index e03b112194786..ff7bdb7e7e1a6 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -2611,7 +2611,11 @@ class ASTContext : public RefCountedBase { /// /// \returns if this is an array type, the completely unqualified array type /// that corresponds to it. Otherwise, returns T.getUnqualifiedType(). - QualType getUnqualifiedArrayType(QualType T, Qualifiers ); + QualType getUnqualifiedArrayType(QualType T, Qualifiers ) const; + QualType getUnqualifiedArrayType(QualType T) const { +Qualifiers Quals; +return getUnqualifiedArrayType(T, Quals); + } /// Determine whether the given types are equivalent after /// cvr-qualifiers have been removed. diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index da3834f19ca04..df7f396bae095 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -1605,6 +1605,10 @@ class QualType { QualType stripObjCKindOfType(const ASTContext ) const; /// Remove all qualifiers including _Atomic. + /// + /// Like getUnqualifiedType(), the type may still be qualified if it is a + /// sugared array type. To strip qualifiers even from within a sugared array + /// type, use ASTContext::getUnqualifiedArrayType. QualType getAtomicUnqualifiedType() const; private: @@ -2092,8 +2096,8 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase { LLVM_PREFERRED_TYPE(TypeBitfields) unsigned : NumTypeBits; -LLVM_PREFERRED_TYPE(bool) -unsigned IsUnqual : 1; // If true: typeof_unqual, else: typeof +LLVM_PREFERRED_TYPE(TypeOfKind) +unsigned Kind : 1; }; class UsingBitfields { @@ -5273,19 +5277,20 @@ class MacroQualifiedType : public Type { /// extension) or a `typeof_unqual` expression (a C23 feature). class TypeOfExprType : public Type { Expr *TOExpr; + const ASTContext protected: friend class ASTContext; // ASTContext creates these. - TypeOfExprType(Expr *E, TypeOfKind Kind, QualType Can = QualType()); + TypeOfExprType(const ASTContext , Expr *E, TypeOfKind Kind, + QualType Can = QualType()); public: Expr *getUnderlyingExpr() const { return TOExpr; } /// Returns the kind of 'typeof' type this is. TypeOfKind getKind() const { -return TypeOfBits.IsUnqual ? TypeOfKind::Unqualified - : TypeOfKind::Qualified; +return static_cast(TypeOfBits.Kind); } /// Remove a single level of sugar. @@ -5306,7 +5311,8 @@ class TypeOfExprType : public Type { class DependentTypeOfExprType : public TypeOfExprType, public llvm::FoldingSetNode { public: - DependentTypeOfExprType(Expr *E, TypeOfKind Kind) : TypeOfExprType(E, Kind) {} + DependentTypeOfExprType(const ASTContext , Expr *E, TypeOfKind Kind) + : TypeOfExprType(Context, E, Kind) {} void Profile(llvm::FoldingSetNodeID , const ASTContext ) { Profile(ID, Context, getUnderlyingExpr(), @@ -5323,32 +5329,23 @@ class TypeOfType : public Type { friend class ASTContext; // ASTContext creates these. QualType TOType; + const ASTContext - TypeOfType(QualType T, QualType Can, TypeOfKind Kind) - : Type(TypeOf, - Kind == TypeOfKind::Unqualified ? Can.getAtomicUnqualifiedType() - : Can, - T->getDependence()), -TOType(T) { -TypeOfBits.IsUnqual = Kind == TypeOfKind::Unqualified; - } + TypeOfType(const ASTContext , QualType T, QualType Can, + TypeOfKind Kind); public: QualType getUnmodifiedType() const { return TOType; } /// Remove a single level of sugar. - QualType desugar() const { -QualType QT = getUnmodifiedType(); -return TypeOfBits.IsUnqual ? QT.getAtomicUnqualifiedType() : QT; - } + QualType desugar() const; /// Returns whether this type directly provides sugar. bool isSugared() const { return true; } /// Returns the kind of 'typeof' type this is. TypeOfKind getKind() const { -return TypeOfBits.IsUnqual ? TypeOfKind::Unqualified - :
[clang] [Clang] [C23] Fix typeof_unqual for qualified array types (PR #92767)
llvmbot wrote: @llvm/pr-subscribers-clang Author: Mital Ashok (MitalAshok) Changes Properly remove qualifiers for both the element type and the array type Fixes #92667 --- Full diff: https://github.com/llvm/llvm-project/pull/92767.diff 5 Files Affected: - (modified) clang/include/clang/AST/ASTContext.h (+5-1) - (modified) clang/include/clang/AST/Type.h (+17-20) - (modified) clang/lib/AST/ASTContext.cpp (+7-7) - (modified) clang/lib/AST/Type.cpp (+30-8) - (modified) clang/test/Sema/c2x-typeof.c (+25) ``diff diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index e03b112194786..ff7bdb7e7e1a6 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -2611,7 +2611,11 @@ class ASTContext : public RefCountedBase { /// /// \returns if this is an array type, the completely unqualified array type /// that corresponds to it. Otherwise, returns T.getUnqualifiedType(). - QualType getUnqualifiedArrayType(QualType T, Qualifiers ); + QualType getUnqualifiedArrayType(QualType T, Qualifiers ) const; + QualType getUnqualifiedArrayType(QualType T) const { +Qualifiers Quals; +return getUnqualifiedArrayType(T, Quals); + } /// Determine whether the given types are equivalent after /// cvr-qualifiers have been removed. diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index da3834f19ca04..df7f396bae095 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -1605,6 +1605,10 @@ class QualType { QualType stripObjCKindOfType(const ASTContext ) const; /// Remove all qualifiers including _Atomic. + /// + /// Like getUnqualifiedType(), the type may still be qualified if it is a + /// sugared array type. To strip qualifiers even from within a sugared array + /// type, use ASTContext::getUnqualifiedArrayType. QualType getAtomicUnqualifiedType() const; private: @@ -2092,8 +2096,8 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase { LLVM_PREFERRED_TYPE(TypeBitfields) unsigned : NumTypeBits; -LLVM_PREFERRED_TYPE(bool) -unsigned IsUnqual : 1; // If true: typeof_unqual, else: typeof +LLVM_PREFERRED_TYPE(TypeOfKind) +unsigned Kind : 1; }; class UsingBitfields { @@ -5273,19 +5277,20 @@ class MacroQualifiedType : public Type { /// extension) or a `typeof_unqual` expression (a C23 feature). class TypeOfExprType : public Type { Expr *TOExpr; + const ASTContext protected: friend class ASTContext; // ASTContext creates these. - TypeOfExprType(Expr *E, TypeOfKind Kind, QualType Can = QualType()); + TypeOfExprType(const ASTContext , Expr *E, TypeOfKind Kind, + QualType Can = QualType()); public: Expr *getUnderlyingExpr() const { return TOExpr; } /// Returns the kind of 'typeof' type this is. TypeOfKind getKind() const { -return TypeOfBits.IsUnqual ? TypeOfKind::Unqualified - : TypeOfKind::Qualified; +return static_cast(TypeOfBits.Kind); } /// Remove a single level of sugar. @@ -5306,7 +5311,8 @@ class TypeOfExprType : public Type { class DependentTypeOfExprType : public TypeOfExprType, public llvm::FoldingSetNode { public: - DependentTypeOfExprType(Expr *E, TypeOfKind Kind) : TypeOfExprType(E, Kind) {} + DependentTypeOfExprType(const ASTContext , Expr *E, TypeOfKind Kind) + : TypeOfExprType(Context, E, Kind) {} void Profile(llvm::FoldingSetNodeID , const ASTContext ) { Profile(ID, Context, getUnderlyingExpr(), @@ -5323,32 +5329,23 @@ class TypeOfType : public Type { friend class ASTContext; // ASTContext creates these. QualType TOType; + const ASTContext - TypeOfType(QualType T, QualType Can, TypeOfKind Kind) - : Type(TypeOf, - Kind == TypeOfKind::Unqualified ? Can.getAtomicUnqualifiedType() - : Can, - T->getDependence()), -TOType(T) { -TypeOfBits.IsUnqual = Kind == TypeOfKind::Unqualified; - } + TypeOfType(const ASTContext , QualType T, QualType Can, + TypeOfKind Kind); public: QualType getUnmodifiedType() const { return TOType; } /// Remove a single level of sugar. - QualType desugar() const { -QualType QT = getUnmodifiedType(); -return TypeOfBits.IsUnqual ? QT.getAtomicUnqualifiedType() : QT; - } + QualType desugar() const; /// Returns whether this type directly provides sugar. bool isSugared() const { return true; } /// Returns the kind of 'typeof' type this is. TypeOfKind getKind() const { -return TypeOfBits.IsUnqual ? TypeOfKind::Unqualified - : TypeOfKind::Qualified; +return static_cast(TypeOfBits.Kind); } static bool classof(const Type *T) { return T->getTypeClass() == TypeOf; } diff --git a/clang/lib/AST/ASTContext.cpp
[clang] [Clang] [C23] Fix typeof_unqual for qualified array types (PR #92767)
https://github.com/MitalAshok created https://github.com/llvm/llvm-project/pull/92767 Properly remove qualifiers for both the element type and the array type Fixes #92667 >From f87cb4c754a477515746e2ac2f8906b93ccd1fe3 Mon Sep 17 00:00:00 2001 From: Mital Ashok Date: Mon, 20 May 2024 15:58:58 +0100 Subject: [PATCH] [Clang] [C23] Fix typeof_unqual for qualified array types Properly remove qualifiers for both the element type and the array type Fixes #92667 --- clang/include/clang/AST/ASTContext.h | 6 - clang/include/clang/AST/Type.h | 37 +-- clang/lib/AST/ASTContext.cpp | 14 +- clang/lib/AST/Type.cpp | 38 ++-- clang/test/Sema/c2x-typeof.c | 25 ++ 5 files changed, 84 insertions(+), 36 deletions(-) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index e03b112194786..ff7bdb7e7e1a6 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -2611,7 +2611,11 @@ class ASTContext : public RefCountedBase { /// /// \returns if this is an array type, the completely unqualified array type /// that corresponds to it. Otherwise, returns T.getUnqualifiedType(). - QualType getUnqualifiedArrayType(QualType T, Qualifiers ); + QualType getUnqualifiedArrayType(QualType T, Qualifiers ) const; + QualType getUnqualifiedArrayType(QualType T) const { +Qualifiers Quals; +return getUnqualifiedArrayType(T, Quals); + } /// Determine whether the given types are equivalent after /// cvr-qualifiers have been removed. diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index da3834f19ca04..df7f396bae095 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -1605,6 +1605,10 @@ class QualType { QualType stripObjCKindOfType(const ASTContext ) const; /// Remove all qualifiers including _Atomic. + /// + /// Like getUnqualifiedType(), the type may still be qualified if it is a + /// sugared array type. To strip qualifiers even from within a sugared array + /// type, use ASTContext::getUnqualifiedArrayType. QualType getAtomicUnqualifiedType() const; private: @@ -2092,8 +2096,8 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase { LLVM_PREFERRED_TYPE(TypeBitfields) unsigned : NumTypeBits; -LLVM_PREFERRED_TYPE(bool) -unsigned IsUnqual : 1; // If true: typeof_unqual, else: typeof +LLVM_PREFERRED_TYPE(TypeOfKind) +unsigned Kind : 1; }; class UsingBitfields { @@ -5273,19 +5277,20 @@ class MacroQualifiedType : public Type { /// extension) or a `typeof_unqual` expression (a C23 feature). class TypeOfExprType : public Type { Expr *TOExpr; + const ASTContext protected: friend class ASTContext; // ASTContext creates these. - TypeOfExprType(Expr *E, TypeOfKind Kind, QualType Can = QualType()); + TypeOfExprType(const ASTContext , Expr *E, TypeOfKind Kind, + QualType Can = QualType()); public: Expr *getUnderlyingExpr() const { return TOExpr; } /// Returns the kind of 'typeof' type this is. TypeOfKind getKind() const { -return TypeOfBits.IsUnqual ? TypeOfKind::Unqualified - : TypeOfKind::Qualified; +return static_cast(TypeOfBits.Kind); } /// Remove a single level of sugar. @@ -5306,7 +5311,8 @@ class TypeOfExprType : public Type { class DependentTypeOfExprType : public TypeOfExprType, public llvm::FoldingSetNode { public: - DependentTypeOfExprType(Expr *E, TypeOfKind Kind) : TypeOfExprType(E, Kind) {} + DependentTypeOfExprType(const ASTContext , Expr *E, TypeOfKind Kind) + : TypeOfExprType(Context, E, Kind) {} void Profile(llvm::FoldingSetNodeID , const ASTContext ) { Profile(ID, Context, getUnderlyingExpr(), @@ -5323,32 +5329,23 @@ class TypeOfType : public Type { friend class ASTContext; // ASTContext creates these. QualType TOType; + const ASTContext - TypeOfType(QualType T, QualType Can, TypeOfKind Kind) - : Type(TypeOf, - Kind == TypeOfKind::Unqualified ? Can.getAtomicUnqualifiedType() - : Can, - T->getDependence()), -TOType(T) { -TypeOfBits.IsUnqual = Kind == TypeOfKind::Unqualified; - } + TypeOfType(const ASTContext , QualType T, QualType Can, + TypeOfKind Kind); public: QualType getUnmodifiedType() const { return TOType; } /// Remove a single level of sugar. - QualType desugar() const { -QualType QT = getUnmodifiedType(); -return TypeOfBits.IsUnqual ? QT.getAtomicUnqualifiedType() : QT; - } + QualType desugar() const; /// Returns whether this type directly provides sugar. bool isSugared() const { return true; } /// Returns the kind of 'typeof' type this is. TypeOfKind getKind() const { -return