From 075f8f1b6bed4d1b224c74f87508534cc6392ce6 Mon Sep 17 00:00:00 2001
From: Abramo Bagnara <abramo.bagnara@gmail.com>
Date: Fri, 10 Dec 2010 16:29:40 +0000
Subject: [PATCH] Added ParenType type node.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@121488 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/clang/AST/ASTContext.h            |  3 +
 include/clang/AST/RecursiveASTVisitor.h   |  8 +++
 include/clang/AST/Type.h                  | 45 +++++++++++++--
 include/clang/AST/TypeLoc.h               | 40 ++++++++++++++
 include/clang/AST/TypeNodes.def           |  1 +
 include/clang/Sema/DeclSpec.h             | 67 +++++++++++++++++++++--
 include/clang/Sema/Sema.h                 |  2 +
 include/clang/Serialization/ASTBitCodes.h |  4 +-
 lib/AST/ASTContext.cpp                    | 34 ++++++++++++
 lib/AST/ASTDiagnostic.cpp                 |  6 +-
 lib/AST/ASTImporter.cpp                   |  7 +++
 lib/AST/Type.cpp                          |  6 ++
 lib/AST/TypePrinter.cpp                   |  6 ++
 lib/CodeGen/CGDebugInfo.cpp               |  4 ++
 lib/CodeGen/CodeGenFunction.cpp           |  5 ++
 lib/Parse/ParseCXXInlineMethods.cpp       |  3 +-
 lib/Parse/ParseDecl.cpp                   |  4 +-
 lib/Parse/ParseDeclCXX.cpp                |  2 +-
 lib/Parse/Parser.cpp                      | 14 ++---
 lib/Sema/SemaCodeComplete.cpp             |  3 +
 lib/Sema/SemaDecl.cpp                     | 20 ++++---
 lib/Sema/SemaDeclCXX.cpp                  |  6 +-
 lib/Sema/SemaExceptionSpec.cpp            |  2 +
 lib/Sema/SemaTemplate.cpp                 |  4 +-
 lib/Sema/SemaType.cpp                     | 15 ++++-
 lib/Sema/TreeTransform.h                  | 30 ++++++++++
 lib/Serialization/ASTReader.cpp           | 13 +++++
 lib/Serialization/ASTWriter.cpp           |  9 +++
 tools/libclang/CIndex.cpp                 |  5 ++
 29 files changed, 329 insertions(+), 39 deletions(-)

diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 9b5826b5d9..745b6a38db 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -101,6 +101,7 @@ class ASTContext {
   llvm::FoldingSet<SubstTemplateTypeParmType> SubstTemplateTypeParmTypes;
   llvm::ContextualFoldingSet<TemplateSpecializationType, ASTContext&>
     TemplateSpecializationTypes;
+  llvm::FoldingSet<ParenType> ParenTypes;
   llvm::FoldingSet<ElaboratedType> ElaboratedTypes;
   llvm::FoldingSet<DependentNameType> DependentNameTypes;
   llvm::ContextualFoldingSet<DependentTemplateSpecializationType, ASTContext&>
@@ -685,6 +686,8 @@ public:
                                     const TemplateArgumentListInfo &Args,
                                     QualType Canon = QualType());
 
+  QualType getParenType(QualType NamedType);
+
   QualType getElaboratedType(ElaboratedTypeKeyword Keyword,
                              NestedNameSpecifier *NNS,
                              QualType NamedType);
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index 269f03d545..085e65ce02 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -718,6 +718,10 @@ DEF_TRAVERSE_TYPE(TemplateSpecializationType, {
 
 DEF_TRAVERSE_TYPE(InjectedClassNameType, { })
 
+DEF_TRAVERSE_TYPE(ParenType, {
+    TRY_TO(TraverseType(T->getInnerType()));
+  })
+
 DEF_TRAVERSE_TYPE(ElaboratedType, {
     if (T->getQualifier()) {
       TRY_TO(TraverseNestedNameSpecifier(T->getQualifier()));
@@ -915,6 +919,10 @@ DEF_TRAVERSE_TYPELOC(TemplateSpecializationType, {
 
 DEF_TRAVERSE_TYPELOC(InjectedClassNameType, { })
 
+DEF_TRAVERSE_TYPELOC(ParenType, {
+    TRY_TO(TraverseTypeLoc(TL.getInnerLoc()));
+  })
+
 // FIXME: use the sourceloc on qualifier?
 DEF_TRAVERSE_TYPELOC(ElaboratedType, {
     if (TL.getTypePtr()->getQualifier()) {
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index be23abd095..19f7f47837 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -661,6 +661,12 @@ public:
     return getSplitDesugaredType(*this);
   }
 
+  /// IgnoreParens - Returns the specified type after dropping any
+  /// outer-level parentheses.
+  QualType IgnoreParens() const {
+    return QualType::IgnoreParens(*this);
+  }
+
   /// operator==/!= - Indicate whether the specified types and qualifiers are
   /// identical.
   friend bool operator==(const QualType &LHS, const QualType &RHS) {
@@ -724,6 +730,7 @@ private:
   static bool isConstant(QualType T, ASTContext& Ctx);
   static QualType getDesugaredType(QualType T, ASTContext &Context);
   static SplitQualType getSplitDesugaredType(QualType T);
+  static QualType IgnoreParens(QualType T);
 };
 
 } // end clang.
@@ -1392,6 +1399,36 @@ public:
   static bool classof(const ComplexType *) { return true; }
 };
 
+/// ParenType - Sugar for parentheses used when specifying types.
+///
+class ParenType : public Type, public llvm::FoldingSetNode {
+  QualType Inner;
+
+  ParenType(QualType InnerType, QualType CanonType) :
+    Type(Paren, CanonType, InnerType->isDependentType(),
+         InnerType->isVariablyModifiedType()),
+    Inner(InnerType) {
+  }
+  friend class ASTContext;  // ASTContext creates these.
+
+public:
+
+  QualType getInnerType() const { return Inner; }
+
+  bool isSugared() const { return true; }
+  QualType desugar() const { return getInnerType(); }
+
+  void Profile(llvm::FoldingSetNodeID &ID) {
+    Profile(ID, getInnerType());
+  }
+  static void Profile(llvm::FoldingSetNodeID &ID, QualType Inner) {
+    Inner.Profile(ID);
+  }
+
+  static bool classof(const Type *T) { return T->getTypeClass() == Paren; }
+  static bool classof(const ParenType *) { return true; }
+};
+
 /// PointerType - C99 6.7.5.1 - Pointer Declarators.
 ///
 class PointerType : public Type, public llvm::FoldingSetNode {
@@ -2026,12 +2063,12 @@ class FunctionType : public Type {
   QualType ResultType;
 
  public:
-  // This class is used for passing arround the information needed to
+  // This class is used for passing around the information needed to
   // construct a call. It is not actually used for storage, just for
   // factoring together common arguments.
-  // If you add a field (say Foo), other than the obvious places (both, constructors,
-  // compile failures), what you need to update is
-  // * Operetor==
+  // If you add a field (say Foo), other than the obvious places (both,
+  // constructors, compile failures), what you need to update is
+  // * Operator==
   // * getFoo
   // * withFoo
   // * functionType. Add Foo, getFoo.
diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h
index e955d07770..1ec0e6cdd1 100644
--- a/include/clang/AST/TypeLoc.h
+++ b/include/clang/AST/TypeLoc.h
@@ -694,6 +694,46 @@ public:
   }
 };
 
+struct ParenLocInfo {
+  SourceLocation LParenLoc;
+  SourceLocation RParenLoc;
+};
+
+class ParenTypeLoc
+  : public ConcreteTypeLoc<UnqualTypeLoc, ParenTypeLoc, ParenType,
+                           ParenLocInfo> {
+public:
+  SourceLocation getLParenLoc() const {
+    return this->getLocalData()->LParenLoc;
+  }
+  SourceLocation getRParenLoc() const {
+    return this->getLocalData()->RParenLoc;
+  }
+  void setLParenLoc(SourceLocation Loc) {
+    this->getLocalData()->LParenLoc = Loc;
+  }
+  void setRParenLoc(SourceLocation Loc) {
+    this->getLocalData()->RParenLoc = Loc;
+  }
+
+  SourceRange getLocalSourceRange() const {
+    return SourceRange(getLParenLoc(), getRParenLoc());
+  }
+
+  void initializeLocal(SourceLocation Loc) {
+    setLParenLoc(Loc);
+    setRParenLoc(Loc);
+  }
+
+  TypeLoc getInnerLoc() const {
+    return getInnerTypeLoc();
+  }
+
+  QualType getInnerType() const {
+    return this->getTypePtr()->getInnerType();
+  }
+};
+
 
 struct PointerLikeLocInfo {
   SourceLocation StarLoc;
diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def
index 9cb56861a9..5355af1c08 100644
--- a/include/clang/AST/TypeNodes.def
+++ b/include/clang/AST/TypeNodes.def
@@ -79,6 +79,7 @@ ABSTRACT_TYPE(Function, Type)
 TYPE(FunctionProto, FunctionType)
 TYPE(FunctionNoProto, FunctionType)
 DEPENDENT_TYPE(UnresolvedUsing, Type)
+NON_CANONICAL_TYPE(Paren, Type)
 NON_CANONICAL_TYPE(Typedef, Type)
 NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOfExpr, Type)
 NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOf, Type)
diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h
index 5c043cd261..bd419e3e69 100644
--- a/include/clang/Sema/DeclSpec.h
+++ b/include/clang/Sema/DeclSpec.h
@@ -26,6 +26,7 @@
 #include "clang/Basic/OperatorKinds.h"
 #include "clang/Basic/Specifiers.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/ErrorHandling.h"
 
 namespace clang {
   class LangOptions;
@@ -799,7 +800,7 @@ typedef llvm::SmallVector<Token, 4> CachedTokens;
 /// This is intended to be a small value object.
 struct DeclaratorChunk {
   enum {
-    Pointer, Reference, Array, Function, BlockPointer, MemberPointer
+    Pointer, Reference, Array, Function, BlockPointer, MemberPointer, Paren
   } Kind;
 
   /// Loc - The place where this type was defined.
@@ -1006,6 +1007,7 @@ struct DeclaratorChunk {
     case DeclaratorChunk::Reference:     return Ref.destroy();
     case DeclaratorChunk::Array:         return Arr.destroy();
     case DeclaratorChunk::MemberPointer: return Mem.destroy();
+    case DeclaratorChunk::Paren:         return;
     }
   }
 
@@ -1013,14 +1015,16 @@ struct DeclaratorChunk {
   /// them.
   const AttributeList *getAttrs() const {
     switch (Kind) {
-    default: assert(0 && "Unknown declarator kind!");
     case Pointer:       return Ptr.AttrList;
     case Reference:     return Ref.AttrList;
     case MemberPointer: return Mem.AttrList;
     case Array:         return 0;
     case Function:      return 0;
     case BlockPointer:  return Cls.AttrList;
+    case Paren:         return 0;
     }
+    llvm_unreachable("Unknown declarator kind!");
+    return 0;
   }
 
 
@@ -1104,6 +1108,18 @@ struct DeclaratorChunk {
     new (I.Mem.ScopeMem.Mem) CXXScopeSpec(SS);
     return I;
   }
+
+  /// getParen - Return a DeclaratorChunk for a paren.
+  ///
+  static DeclaratorChunk getParen(SourceLocation LParenLoc,
+                                  SourceLocation RParenLoc) {
+    DeclaratorChunk I;
+    I.Kind          = Paren;
+    I.Loc           = LParenLoc;
+    I.EndLoc        = RParenLoc;
+    return I;
+  }
+
 };
 
 /// Declarator - Information about one declarator, including the parsed type
@@ -1323,11 +1339,52 @@ public:
     DeclTypeInfo.erase(DeclTypeInfo.begin());
   }
 
+  /// isFunctionDeclarator - This method returns true if the declarator
+  /// is a function declarator (looking through parentheses).
+  /// If true is returned, then the reference type parameter idx is
+  /// assigned with the index of the declaration chunk.
+  bool isFunctionDeclarator(unsigned& idx) const {
+    for (unsigned i = 0, i_end = DeclTypeInfo.size(); i < i_end; ++i) {
+      switch (DeclTypeInfo[i].Kind) {
+      case DeclaratorChunk::Function:
+        idx = i;
+        return true;
+      case DeclaratorChunk::Paren:
+        continue;
+      case DeclaratorChunk::Pointer:
+      case DeclaratorChunk::Reference:
+      case DeclaratorChunk::Array:
+      case DeclaratorChunk::BlockPointer:
+      case DeclaratorChunk::MemberPointer:
+        return false;
+      }
+      llvm_unreachable("Invalid type chunk");
+      return false;
+    }
+    return false;
+  }
+
   /// isFunctionDeclarator - Once this declarator is fully parsed and formed,
-  /// this method returns true if the identifier is a function declarator.
+  /// this method returns true if the identifier is a function declarator
+  /// (looking through parentheses).
   bool isFunctionDeclarator() const {
-    return !DeclTypeInfo.empty() &&
-           DeclTypeInfo[0].Kind == DeclaratorChunk::Function;
+    unsigned index;
+    return isFunctionDeclarator(index);
+  }
+
+  /// getFunctionTypeInfo - Retrieves the function type info object
+  /// (looking through parentheses).
+  DeclaratorChunk::FunctionTypeInfo &getFunctionTypeInfo() {
+    assert(isFunctionDeclarator() && "Not a function declarator!");
+    unsigned index;
+    isFunctionDeclarator(index);
+    return DeclTypeInfo[index].Fun;
+  }
+
+  /// getFunctionTypeInfo - Retrieves the function type info object
+  /// (looking through parentheses).
+  const DeclaratorChunk::FunctionTypeInfo &getFunctionTypeInfo() const {
+    return const_cast<Declarator*>(this)->getFunctionTypeInfo();
   }
 
   /// AddAttributes - simply adds the attribute list to the Declarator.
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 541f726e5a..0aff2f6bff 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -619,6 +619,8 @@ public:
                                   DeclarationName Entity);
   QualType BuildBlockPointerType(QualType T,
                                  SourceLocation Loc, DeclarationName Entity);
+  QualType BuildParenType(QualType T);
+
   TypeSourceInfo *GetTypeForDeclarator(Declarator &D, Scope *S,
                                        TagDecl **OwnedDecl = 0);
   TypeSourceInfo *GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h
index 29eb49106f..d32cc2717b 100644
--- a/include/clang/Serialization/ASTBitCodes.h
+++ b/include/clang/Serialization/ASTBitCodes.h
@@ -549,7 +549,9 @@ namespace clang {
       /// \brief A DependentTemplateSpecializationType record.
       TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION = 32,
       /// \brief A DependentSizedArrayType record.
-      TYPE_DEPENDENT_SIZED_ARRAY    = 33
+      TYPE_DEPENDENT_SIZED_ARRAY    = 33,
+      /// \brief A ParenType record.
+      TYPE_PAREN                    = 34
     };
 
     /// \brief The type IDs for special types constructed by semantic
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index dfdc505b1a..ecba4a136f 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -811,6 +811,9 @@ ASTContext::getTypeInfo(const Type *T) {
     return getTypeInfo(cast<SubstTemplateTypeParmType>(T)->
                        getReplacementType().getTypePtr());
 
+  case Type::Paren:
+    return getTypeInfo(cast<ParenType>(T)->getInnerType().getTypePtr());
+
   case Type::Typedef: {
     const TypedefDecl *Typedef = cast<TypedefType>(T)->getDecl();
     std::pair<uint64_t, unsigned> Info
@@ -1147,6 +1150,13 @@ static QualType getExtFunctionType(ASTContext& Context, QualType T,
       return T;
 
     ResultType = Context.getPointerType(ResultType);
+  } else if (const ParenType *Paren = T->getAs<ParenType>()) {
+    QualType Inner = Paren->getInnerType();
+    ResultType = getExtFunctionType(Context, Inner, Info);
+    if (ResultType == Inner)
+      return T;
+
+    ResultType = Context.getParenType(ResultType);
   } else if (const BlockPointerType *BlockPointer
                                               = T->getAs<BlockPointerType>()) {
     QualType Pointee = BlockPointer->getPointeeType();
@@ -2095,6 +2105,30 @@ ASTContext::getElaboratedType(ElaboratedTypeKeyword Keyword,
   return QualType(T, 0);
 }
 
+QualType
+ASTContext::getParenType(QualType InnerType) {
+  llvm::FoldingSetNodeID ID;
+  ParenType::Profile(ID, InnerType);
+
+  void *InsertPos = 0;
+  ParenType *T = ParenTypes.FindNodeOrInsertPos(ID, InsertPos);
+  if (T)
+    return QualType(T, 0);
+
+  QualType Canon = InnerType;
+  if (!Canon.isCanonical()) {
+    Canon = getCanonicalType(InnerType);
+    ParenType *CheckT = ParenTypes.FindNodeOrInsertPos(ID, InsertPos);
+    assert(!CheckT && "Paren canonical type broken");
+    (void)CheckT;
+  }
+
+  T = new (*this) ParenType(InnerType, Canon);
+  Types.push_back(T);
+  ParenTypes.InsertNode(T, InsertPos);
+  return QualType(T, 0);
+}
+
 QualType ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword,
                                           NestedNameSpecifier *NNS,
                                           const IdentifierInfo *Name,
diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp
index 8d5e408465..bd128f0514 100644
--- a/lib/AST/ASTDiagnostic.cpp
+++ b/lib/AST/ASTDiagnostic.cpp
@@ -32,7 +32,11 @@ static QualType Desugar(ASTContext &Context, QualType QT, bool &ShouldAKA) {
       QT = cast<ElaboratedType>(Ty)->desugar();
       continue;
     }
-
+    // ... or a paren type ...
+    if (isa<ParenType>(Ty)) {
+      QT = cast<ParenType>(Ty)->desugar();
+      continue;
+    }
     // ...or a substituted template type parameter.
     if (isa<SubstTemplateTypeParmType>(Ty)) {
       QT = cast<SubstTemplateTypeParmType>(Ty)->desugar();
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index 4094c88e13..8415977349 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -553,6 +553,13 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
       
     break;
       
+  case Type::Paren:
+    if (!IsStructurallyEquivalent(Context,
+                                  cast<ParenType>(T1)->getInnerType(),
+                                  cast<ParenType>(T2)->getInnerType()))
+      return false;
+    break;
+
   case Type::Typedef:
     if (!IsStructurallyEquivalent(Context,
                                   cast<TypedefType>(T1)->getDecl(),
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 705b097212..ed05a39305 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -171,6 +171,12 @@ SplitQualType QualType::getSplitDesugaredType(QualType T) {
   }
 }
 
+QualType QualType::IgnoreParens(QualType T) {
+  while (const ParenType *PT = T->getAs<ParenType>())
+    T = PT->getInnerType();
+  return T;
+}
+
 /// getUnqualifiedDesugaredType - Pull any qualifiers and syntactic
 /// sugar off the given type.  This should produce an object of the
 /// same dynamic type as the canonical type.
diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp
index 0e37acb40f..15c3fb2fbf 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -618,6 +618,12 @@ void TypePrinter::printElaborated(const ElaboratedType *T, std::string &S) {
     S = MyString + ' ' + S;  
 }
 
+void TypePrinter::printParen(const ParenType *T, std::string &S) {
+  if (!S.empty() && !isa<FunctionType>(T->getInnerType()))
+    S = '(' + S + ')';
+  print(T->getInnerType(), S);
+}
+
 void TypePrinter::printDependentName(const DependentNameType *T, std::string &S) { 
   std::string MyString;
   
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index 3e77769466..615972afbc 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -1327,6 +1327,9 @@ static QualType UnwrapTypeForDebugInfo(QualType T) {
     case Type::Elaborated:
       T = cast<ElaboratedType>(T)->getNamedType();
       break;
+    case Type::Paren:
+      T = cast<ParenType>(T)->getInnerType();
+      break;
     case Type::SubstTemplateTypeParm:
       T = cast<SubstTemplateTypeParmType>(T)->getReplacementType();
       break;
@@ -1422,6 +1425,7 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty,
 
   case Type::TemplateSpecialization:
   case Type::Elaborated:
+  case Type::Paren:
   case Type::SubstTemplateTypeParm:
   case Type::TypeOfExpr:
   case Type::TypeOf:
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index efeca2d538..7bd0c3da9e 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -656,6 +656,11 @@ llvm::Value *CodeGenFunction::EmitVLASize(QualType Ty) {
     return 0;
   }
 
+  if (const ParenType *PT = dyn_cast<ParenType>(Ty)) {
+    EmitVLASize(PT->getInnerType());
+    return 0;
+  }
+
   const PointerType *PT = Ty->getAs<PointerType>();
   assert(PT && "unknown VM type!");
   EmitVLASize(PT->getPointeeType());
diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp
index 718c71be02..2341ad39f0 100644
--- a/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/lib/Parse/ParseCXXInlineMethods.cpp
@@ -22,8 +22,7 @@ using namespace clang;
 /// and store its tokens for parsing after the C++ class is complete.
 Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D,
                                 const ParsedTemplateInfo &TemplateInfo) {
-  assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function &&
-         "This isn't a function declarator!");
+  assert(D.isFunctionDeclarator() && "This isn't a function declarator!");
   assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) &&
          "Current token not a '{', ':' or 'try'!");
 
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 9a682b064d..53cccc0819 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -3037,10 +3037,10 @@ void Parser::ParseParenDeclarator(Declarator &D) {
 
     ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator);
     // Match the ')'.
-    SourceLocation Loc = MatchRHSPunctuation(tok::r_paren, StartLoc);
+    SourceLocation EndLoc = MatchRHSPunctuation(tok::r_paren, StartLoc);
+    D.AddTypeInfo(DeclaratorChunk::getParen(StartLoc, EndLoc), EndLoc);
 
     D.setGroupingParens(hadGroupingParens);
-    D.SetRangeEnd(Loc);
     return;
   }
 
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 68797a7542..a2c87f85c3 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -1239,7 +1239,7 @@ void Parser::HandleMemberFunctionDefaultArgs(Declarator& DeclaratorInfo,
   // has any default arguments, we'll need to parse them later.
   LateParsedMethodDeclaration *LateMethod = 0;
   DeclaratorChunk::FunctionTypeInfo &FTI
-    = DeclaratorInfo.getTypeObject(0).Fun;
+    = DeclaratorInfo.getFunctionTypeInfo();
   for (unsigned ParamIdx = 0; ParamIdx < FTI.NumArgs; ++ParamIdx) {
     if (LateMethod || FTI.ArgInfo[ParamIdx].DefaultArgTokens) {
       if (!LateMethod) {
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index f5e4bfb649..f79a2f68c7 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -601,14 +601,13 @@ bool Parser::isDeclarationAfterDeclarator() const {
 /// \brief Determine whether the current token, if it occurs after a
 /// declarator, indicates the start of a function definition.
 bool Parser::isStartOfFunctionDefinition(const ParsingDeclarator &Declarator) {
-  assert(Declarator.getTypeObject(0).Kind == DeclaratorChunk::Function &&
-         "Isn't a function declarator");
+  assert(Declarator.isFunctionDeclarator() && "Isn't a function declarator");
   if (Tok.is(tok::l_brace))   // int X() {}
     return true;
   
   // Handle K&R C argument lists: int X(f) int f; {}
   if (!getLang().CPlusPlus &&
-      Declarator.getTypeObject(0).Fun.isKNRPrototype()) 
+      Declarator.getFunctionTypeInfo().isKNRPrototype()) 
     return isDeclarationSpecifier();
   
   return Tok.is(tok::colon) ||         // X() : Base() {} (used for ctors)
@@ -712,11 +711,8 @@ Parser::ParseDeclarationOrFunctionDefinition(AttributeList *Attr,
 ///         decl-specifier-seq[opt] declarator function-try-block
 ///
 Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
-                                     const ParsedTemplateInfo &TemplateInfo) {
-  const DeclaratorChunk &FnTypeInfo = D.getTypeObject(0);
-  assert(FnTypeInfo.Kind == DeclaratorChunk::Function &&
-         "This isn't a function declarator!");
-  const DeclaratorChunk::FunctionTypeInfo &FTI = FnTypeInfo.Fun;
+                                      const ParsedTemplateInfo &TemplateInfo) {
+  const DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
 
   // If this is C90 and the declspecs were completely missing, fudge in an
   // implicit int.  We do this here because this is the only place where
@@ -793,7 +789,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
 /// types for a function with a K&R-style identifier list for arguments.
 void Parser::ParseKNRParamDeclarations(Declarator &D) {
   // We know that the top-level of this declarator is a function.
-  DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;
+  DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
 
   // Enter function-declaration scope, limiting any declarators to the
   // function prototype scope, including parameter declarators.
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 0e30a2b0ba..2394629be5 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -1919,6 +1919,9 @@ static std::string FormatFunctionParameter(ASTContext &Context,
       if (BlockPointerTypeLoc *BlockPtr
           = dyn_cast<BlockPointerTypeLoc>(&TL)) {
         TL = BlockPtr->getPointeeLoc();
+        // Skip any paren typeloc.
+        while (ParenTypeLoc *ParenPtr = dyn_cast<ParenTypeLoc>(&TL))
+          TL = ParenPtr->getInnerLoc();
         Block = dyn_cast<FunctionProtoTypeLoc>(&TL);
       }
       break;
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 1112d85b8b..522ba36760 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -2571,6 +2571,15 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T,
     FixedType = Context.getPointerType(FixedType);
     return Qs.apply(Context, FixedType);
   }
+  if (const ParenType* PTy = dyn_cast<ParenType>(Ty)) {
+    QualType Inner = PTy->getInnerType();
+    QualType FixedType =
+        TryToFixInvalidVariablyModifiedType(Inner, Context, SizeIsNegative,
+                                            Oversized);
+    if (FixedType.isNull()) return FixedType;
+    FixedType = Context.getParenType(FixedType);
+    return Qs.apply(Context, FixedType);
+  }
 
   const VariableArrayType* VLATy = dyn_cast<VariableArrayType>(T);
   if (!VLATy)
@@ -3456,7 +3465,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
     //   - the type R of the function is some kind of typedef or other reference
     //     to a type name (which eventually refers to a function type).
     bool HasPrototype =
-    (D.getNumTypeObjects() && D.getTypeObject(0).Fun.hasPrototype) ||
+    (D.isFunctionDeclarator() && D.getFunctionTypeInfo().hasPrototype) ||
     (!isa<FunctionType>(R.getTypePtr()) && R->isFunctionProtoType());
   
     NewFD = FunctionDecl::Create(Context, DC,
@@ -3754,7 +3763,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
   // declaration NewFD, if they are available.  First scavenge them into Params.
   llvm::SmallVector<ParmVarDecl*, 16> Params;
   if (D.getNumTypeObjects() > 0) {
-    DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;
+    DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
 
     // Check for C99 6.7.5.3p10 - foo(void) is a non-varargs
     // function that takes no arguments, not a function that takes a
@@ -5088,9 +5097,7 @@ ParmVarDecl *Sema::CheckParameter(DeclContext *DC,
 
 void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
                                            SourceLocation LocAfterDecls) {
-  assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function &&
-         "Not a function declarator!");
-  DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;
+  DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
 
   // Verify 6.9.1p6: 'every identifier in the identifier list shall be declared'
   // for a K&R function.
@@ -5124,8 +5131,7 @@ void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
 Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope,
                                          Declarator &D) {
   assert(getCurFunctionDecl() == 0 && "Function parsing confused");
-  assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function &&
-         "Not a function declarator!");
+  assert(D.isFunctionDeclarator() && "Not a function declarator!");
   Scope *ParentScope = FnBodyScope->getParent();
 
   Decl *DP = HandleDeclarator(ParentScope, D,
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index b5e6321276..be1979e26e 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -2835,7 +2835,7 @@ QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R,
     SC = SC_None;
   }
 
-  DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;
+  DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
   if (FTI.TypeQuals != 0) {
     if (FTI.TypeQuals & Qualifiers::Const)
       Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor)
@@ -2984,7 +2984,7 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R,
       << SourceRange(D.getIdentifierLoc());
   }
 
-  DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;
+  DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
   if (FTI.TypeQuals != 0 && !D.isInvalidType()) {
     if (FTI.TypeQuals & Qualifiers::Const)
       Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor)
@@ -3074,7 +3074,7 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R,
     Diag(D.getIdentifierLoc(), diag::err_conv_function_with_params);
 
     // Delete the parameters.
-    D.getTypeObject(0).Fun.freeArgs();
+    D.getFunctionTypeInfo().freeArgs();
     D.setInvalidType();
   } else if (Proto->isVariadic()) {
     Diag(D.getIdentifierLoc(), diag::err_conv_function_variadic);
diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp
index c902e77870..885e52dd76 100644
--- a/lib/Sema/SemaExceptionSpec.cpp
+++ b/lib/Sema/SemaExceptionSpec.cpp
@@ -81,6 +81,7 @@ bool Sema::CheckSpecifiedExceptionType(QualType T, const SourceRange &Range) {
 /// to member to a function with an exception specification. This means that
 /// it is invalid to add another level of indirection.
 bool Sema::CheckDistantExceptionSpec(QualType T) {
+  T = T.IgnoreParens();
   if (const PointerType *PT = T->getAs<PointerType>())
     T = PT->getPointeeType();
   else if (const MemberPointerType *PT = T->getAs<MemberPointerType>())
@@ -88,6 +89,7 @@ bool Sema::CheckDistantExceptionSpec(QualType T) {
   else
     return false;
 
+  T = T.IgnoreParens();
   const FunctionProtoType *FnT = T->getAs<FunctionProtoType>();
   if (!FnT)
     return false;
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index ad0d42a11a..7539a56965 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -4336,9 +4336,7 @@ Decl *Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
                                MultiTemplateParamsArg TemplateParameterLists,
                                             Declarator &D) {
   assert(getCurFunctionDecl() == 0 && "Function parsing confused");
-  assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function &&
-         "Not a function declarator!");
-  DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;
+  DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
 
   if (FTI.hasPrototype) {
     // FIXME: Diagnose arguments without names in C.
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 5f86010602..23c159fbc5 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -521,6 +521,11 @@ QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc,
   return Context.getQualifiedType(T, Qs);
 }
 
+/// \brief Build a paren type including \p T.
+QualType Sema::BuildParenType(QualType T) {
+  return Context.getParenType(T);
+}
+
 /// \brief Build a pointer type.
 ///
 /// \param T The type to which we'll be building a pointer.
@@ -1002,7 +1007,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
   // Check for auto functions and trailing return type and adjust the
   // return type accordingly.
   if (getLangOptions().CPlusPlus0x && D.isFunctionDeclarator()) {
-    const DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;
+    const DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
     if (T == Context.UndeducedAutoTy) {
       if (FTI.TrailingReturnType) {
           T = GetTypeFromParser(ParsedType::getFromOpaquePtr(FTI.TrailingReturnType),
@@ -1082,6 +1087,9 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
     DeclaratorChunk &DeclType = D.getTypeObject(e-i-1);
     switch (DeclType.Kind) {
     default: assert(0 && "Unknown decltype!");
+    case DeclaratorChunk::Paren:
+      T = BuildParenType(T);
+      break;
     case DeclaratorChunk::BlockPointer:
       // If blocks are disabled, emit an error.
       if (!LangOpts.Blocks)
@@ -1678,6 +1686,11 @@ namespace {
       }
       // FIXME: exception specs
     }
+    void VisitParenTypeLoc(ParenTypeLoc TL) {
+      assert(Chunk.Kind == DeclaratorChunk::Paren);
+      TL.setLParenLoc(Chunk.Loc);
+      TL.setRParenLoc(Chunk.EndLoc);
+    }
 
     void VisitTypeLoc(TypeLoc TL) {
       llvm_unreachable("unsupported TypeLoc kind in declarator!");
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index c0bafc7cb0..9f6f84bec8 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -519,6 +519,14 @@ public:
                                              SourceLocation TemplateLoc,
                                        const TemplateArgumentListInfo &Args);
 
+  /// \brief Build a new parenthesized type.
+  ///
+  /// By default, builds a new ParenType type from the inner type.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildParenType(QualType InnerType) {
+    return SemaRef.Context.getParenType(InnerType);
+  }
+
   /// \brief Build a new qualified name type.
   ///
   /// By default, builds a new ElaboratedType type from the keyword,
@@ -3371,6 +3379,28 @@ TreeTransform<Derived>::TransformElaboratedType(TypeLocBuilder &TLB,
   return Result;
 }
 
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformParenType(TypeLocBuilder &TLB,
+                                           ParenTypeLoc TL) {
+  QualType Inner = getDerived().TransformType(TLB, TL.getInnerLoc());
+  if (Inner.isNull())
+    return QualType();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      Inner != TL.getInnerLoc().getType()) {
+    Result = getDerived().RebuildParenType(Inner);
+    if (Result.isNull())
+      return QualType();
+  }
+
+  ParenTypeLoc NewTL = TLB.push<ParenTypeLoc>(Result);
+  NewTL.setLParenLoc(TL.getLParenLoc());
+  NewTL.setRParenLoc(TL.getRParenLoc());
+  return Result;
+}
+
 template<typename Derived>
 QualType TreeTransform<Derived>::TransformDependentNameType(TypeLocBuilder &TLB,
                                                       DependentNameTypeLoc TL) {
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index c3c0aeae67..4e0a7b783b 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -2916,6 +2916,15 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) {
     return T;
   }
 
+  case TYPE_PAREN: {
+    if (Record.size() != 1) {
+      Error("incorrect encoding of paren type");
+      return QualType();
+    }
+    QualType InnerType = GetType(Record[0]);
+    return Context->getParenType(InnerType);
+  }
+
   case TYPE_ELABORATED: {
     unsigned Idx = 0;
     ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++];
@@ -3186,6 +3195,10 @@ void TypeLocReader::VisitTemplateSpecializationTypeLoc(
                                           TL.getTypePtr()->getArg(i).getKind(),
                                           Record, Idx));
 }
+void TypeLocReader::VisitParenTypeLoc(ParenTypeLoc TL) {
+  TL.setLParenLoc(ReadSourceLocation(Record, Idx));
+  TL.setRParenLoc(ReadSourceLocation(Record, Idx));
+}
 void TypeLocReader::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
   TL.setKeywordLoc(ReadSourceLocation(Record, Idx));
   TL.setQualifierRange(Reader.ReadSourceRange(F, Record, Idx));
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index e95e422fbd..7b405e9c8b 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -298,6 +298,11 @@ ASTTypeWriter::VisitDependentTemplateSpecializationType(
   Code = TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION;
 }
 
+void ASTTypeWriter::VisitParenType(const ParenType *T) {
+  Writer.AddTypeRef(T->getInnerType(), Record);
+  Code = TYPE_PAREN;
+}
+
 void ASTTypeWriter::VisitElaboratedType(const ElaboratedType *T) {
   Record.push_back(T->getKeyword());
   Writer.AddNestedNameSpecifier(T->getQualifier(), Record);
@@ -467,6 +472,10 @@ void TypeLocWriter::VisitTemplateSpecializationTypeLoc(
     Writer.AddTemplateArgumentLocInfo(TL.getArgLoc(i).getArgument().getKind(),
                                       TL.getArgLoc(i).getLocInfo(), Record);
 }
+void TypeLocWriter::VisitParenTypeLoc(ParenTypeLoc TL) {
+  Writer.AddSourceLocation(TL.getLParenLoc(), Record);
+  Writer.AddSourceLocation(TL.getRParenLoc(), Record);
+}
 void TypeLocWriter::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
   Writer.AddSourceLocation(TL.getKeywordLoc(), Record);
   Writer.AddSourceRange(TL.getQualifierRange(), Record);
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
index d9aec47558..e8c1a745bf 100644
--- a/tools/libclang/CIndex.cpp
+++ b/tools/libclang/CIndex.cpp
@@ -326,6 +326,7 @@ public:
   bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL);
   bool VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL);
   bool VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL);
+  bool VisitParenTypeLoc(ParenTypeLoc TL);
   bool VisitPointerTypeLoc(PointerTypeLoc TL);
   bool VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL);
   bool VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL);
@@ -1361,6 +1362,10 @@ bool CursorVisitor::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
   return Visit(TL.getPointeeLoc());
 }
 
+bool CursorVisitor::VisitParenTypeLoc(ParenTypeLoc TL) {
+  return Visit(TL.getInnerLoc());
+}
+
 bool CursorVisitor::VisitPointerTypeLoc(PointerTypeLoc TL) {
   return Visit(TL.getPointeeLoc());
 }
-- 
2.40.0