[clang] [Clang] [C23] Fix typeof_unqual for qualified array types (PR #92767)

2024-05-31 Thread Aaron Ballman via cfe-commits

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)

2024-05-31 Thread Aaron Ballman via cfe-commits


@@ -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)

2024-05-30 Thread Mital Ashok via cfe-commits

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)

2024-05-30 Thread Mital Ashok via cfe-commits


@@ -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)

2024-05-30 Thread Mital Ashok via cfe-commits


@@ -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)

2024-05-30 Thread Aaron Ballman via cfe-commits


@@ -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)

2024-05-30 Thread Aaron Ballman via cfe-commits


@@ -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)

2024-05-30 Thread Aaron Ballman via cfe-commits


@@ -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)

2024-05-28 Thread Aaron Ballman via cfe-commits

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)

2024-05-28 Thread Aaron Ballman via cfe-commits

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)

2024-05-21 Thread Mital Ashok via cfe-commits

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)

2024-05-21 Thread Aaron Ballman via cfe-commits

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)

2024-05-21 Thread Aaron Ballman via cfe-commits


@@ -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)

2024-05-21 Thread Aaron Ballman via cfe-commits

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)

2024-05-21 Thread Aaron Ballman via cfe-commits


@@ -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)

2024-05-20 Thread Mital Ashok via cfe-commits

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)

2024-05-20 Thread Mital Ashok via cfe-commits

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)

2024-05-20 Thread via cfe-commits

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)

2024-05-20 Thread Mital Ashok via cfe-commits

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