]> granicus.if.org Git - clang/blobdiff - lib/AST/TypeLoc.cpp
[OPENMP] Initial support for 'task_reduction' clause.
[clang] / lib / AST / TypeLoc.cpp
index 2724e8c46adaca08217f49d6690131df4bb6a432..c9a268655723b53360f047362024b74cb9fbe7d3 100644 (file)
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/Support/raw_ostream.h"
-#include "clang/AST/TypeLocVisitor.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/AST/ASTContext.h"
 #include "clang/AST/Expr.h"
+#include "clang/AST/TypeLocVisitor.h"
 #include "llvm/Support/ErrorHandling.h"
 using namespace clang;
 
+static const unsigned TypeLocMaxDataAlign = alignof(void *);
+
 //===----------------------------------------------------------------------===//
 // TypeLoc Implementation
 //===----------------------------------------------------------------------===//
@@ -38,13 +41,31 @@ SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) {
   return TypeLocRanger().Visit(TL);
 }
 
+namespace {
+  class TypeAligner : public TypeLocVisitor<TypeAligner, unsigned> {
+  public:
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+    unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
+      return TyLoc.getLocalDataAlignment(); \
+    }
+#include "clang/AST/TypeLocNodes.def"
+  };
+}
+
+/// \brief Returns the alignment of the type source info data block.
+unsigned TypeLoc::getLocalAlignmentForType(QualType Ty) {
+  if (Ty.isNull()) return 1;
+  return TypeAligner().Visit(TypeLoc(Ty, nullptr));
+}
+
 namespace {
   class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> {
   public:
 #define ABSTRACT_TYPELOC(CLASS, PARENT)
 #define TYPELOC(CLASS, PARENT) \
     unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
-      return TyLoc.getFullDataSize(); \
+      return TyLoc.getLocalDataSize(); \
     }
 #include "clang/AST/TypeLocNodes.def"
   };
@@ -52,8 +73,18 @@ namespace {
 
 /// \brief Returns the size of the type source info data block.
 unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {
-  if (Ty.isNull()) return 0;
-  return TypeSizer().Visit(TypeLoc(Ty, 0));
+  unsigned Total = 0;
+  TypeLoc TyLoc(Ty, nullptr);
+  unsigned MaxAlign = 1;
+  while (!TyLoc.isNull()) {
+    unsigned Align = getLocalAlignmentForType(TyLoc.getType());
+    MaxAlign = std::max(Align, MaxAlign);
+    Total = llvm::alignTo(Total, Align);
+    Total += TypeSizer().Visit(TyLoc);
+    TyLoc = TyLoc.getNextTypeLoc();
+  }
+  Total = llvm::alignTo(Total, MaxAlign);
+  return Total;
 }
 
 namespace {
@@ -84,7 +115,7 @@ void TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL,
 #define ABSTRACT_TYPELOC(CLASS, PARENT)
 #define TYPELOC(CLASS, PARENT)        \
     case CLASS: {                     \
-      CLASS##TypeLoc TLCasted = cast<CLASS##TypeLoc>(TL); \
+      CLASS##TypeLoc TLCasted = TL.castAs<CLASS##TypeLoc>(); \
       TLCasted.initializeLocal(Context, Loc);  \
       TL = TLCasted.getNextTypeLoc(); \
       if (!TL) return;                \
@@ -95,25 +126,81 @@ void TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL,
   }
 }
 
+namespace {
+  class TypeLocCopier : public TypeLocVisitor<TypeLocCopier> {
+    TypeLoc Source;
+  public:
+    TypeLocCopier(TypeLoc source) : Source(source) { }
+
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT)                          \
+    void Visit##CLASS##TypeLoc(CLASS##TypeLoc dest) {   \
+      dest.copyLocal(Source.castAs<CLASS##TypeLoc>());  \
+    }
+#include "clang/AST/TypeLocNodes.def"
+  };
+}
+
+
+void TypeLoc::copy(TypeLoc other) {
+  assert(getFullDataSize() == other.getFullDataSize());
+
+  // If both data pointers are aligned to the maximum alignment, we
+  // can memcpy because getFullDataSize() accurately reflects the
+  // layout of the data.
+  if (reinterpret_cast<uintptr_t>(Data) ==
+          llvm::alignTo(reinterpret_cast<uintptr_t>(Data),
+                        TypeLocMaxDataAlign) &&
+      reinterpret_cast<uintptr_t>(other.Data) ==
+          llvm::alignTo(reinterpret_cast<uintptr_t>(other.Data),
+                        TypeLocMaxDataAlign)) {
+    memcpy(Data, other.Data, getFullDataSize());
+    return;
+  }
+
+  // Copy each of the pieces.
+  TypeLoc TL(getType(), Data);
+  do {
+    TypeLocCopier(other).Visit(TL);
+    other = other.getNextTypeLoc();
+  } while ((TL = TL.getNextTypeLoc()));
+}
+
 SourceLocation TypeLoc::getBeginLoc() const {
   TypeLoc Cur = *this;
+  TypeLoc LeftMost = Cur;
   while (true) {
     switch (Cur.getTypeLocClass()) {
-    // FIXME: Currently QualifiedTypeLoc does not have a source range
-    // case Qualified:
     case Elaborated:
-    case DependentName:
-    case DependentTemplateSpecialization:
+      LeftMost = Cur;
       break;
+    case FunctionProto:
+      if (Cur.castAs<FunctionProtoTypeLoc>().getTypePtr()
+              ->hasTrailingReturn()) {
+        LeftMost = Cur;
+        break;
+      }
+      /* Fall through */
+    case FunctionNoProto:
+    case ConstantArray:
+    case DependentSizedArray:
+    case IncompleteArray:
+    case VariableArray:
+      // FIXME: Currently QualifiedTypeLoc does not have a source range
+    case Qualified:
+      Cur = Cur.getNextTypeLoc();
+      continue;
     default:
-      TypeLoc Next = Cur.getNextTypeLoc();
-      if (Next.isNull()) break;
-      Cur = Next;
+      if (Cur.getLocalSourceRange().getBegin().isValid())
+        LeftMost = Cur;
+      Cur = Cur.getNextTypeLoc();
+      if (Cur.isNull())
+        break;
       continue;
-    }
+    } // switch
     break;
-  }
-  return Cur.getLocalSourceRange().getBegin();
+  } // while
+  return LeftMost.getLocalSourceRange().getBegin();
 }
 
 SourceLocation TypeLoc::getEndLoc() const {
@@ -123,17 +210,22 @@ SourceLocation TypeLoc::getEndLoc() const {
     switch (Cur.getTypeLocClass()) {
     default:
       if (!Last)
-       Last = Cur;
+        Last = Cur;
       return Last.getLocalSourceRange().getEnd();
     case Paren:
     case ConstantArray:
     case DependentSizedArray:
     case IncompleteArray:
     case VariableArray:
-    case FunctionProto:
     case FunctionNoProto:
       Last = Cur;
       break;
+    case FunctionProto:
+      if (Cur.castAs<FunctionProtoTypeLoc>().getTypePtr()->hasTrailingReturn())
+        Last = TypeLoc();
+      else
+        Last = Cur;
+      break;
     case Pointer:
     case BlockPointer:
     case MemberPointer:
@@ -176,9 +268,9 @@ namespace {
 /// because it's a convenient base class.  Ideally we would not accept
 /// those here, but ideally we would have better implementations for
 /// them.
-bool TypeSpecTypeLoc::classof(const TypeLoc *TL) {
-  if (TL->getType().hasLocalQualifiers()) return false;
-  return TSTChecker().Visit(*TL);
+bool TypeSpecTypeLoc::isKind(const TypeLoc &TL) {
+  if (TL.getType().hasLocalQualifiers()) return false;
+  return TSTChecker().Visit(TL);
 }
 
 // Reimplemented to account for GNU/C++ extension
@@ -196,67 +288,143 @@ SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const {
 TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
   if (needsExtraLocalData())
     return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type);
-  else {
-    switch (getTypePtr()->getKind()) {
-    case BuiltinType::Void:
-      return TST_void;
-    case BuiltinType::Bool:
-      return TST_bool;
-    case BuiltinType::Char_U:
-    case BuiltinType::Char_S:
-      return TST_char;
-    case BuiltinType::Char16:
-      return TST_char16;
-    case BuiltinType::Char32:
-      return TST_char32;
-    case BuiltinType::WChar_S:
-    case BuiltinType::WChar_U:
-      return TST_wchar;
-
-    case BuiltinType::UChar:
-    case BuiltinType::UShort:
-    case BuiltinType::UInt:
-    case BuiltinType::ULong:
-    case BuiltinType::ULongLong:
-    case BuiltinType::UInt128:
-    case BuiltinType::SChar:
-    case BuiltinType::Short:
-    case BuiltinType::Int:
-    case BuiltinType::Long:
-    case BuiltinType::LongLong:
-    case BuiltinType::Int128:
-    case BuiltinType::Half:
-    case BuiltinType::Float:
-    case BuiltinType::Double:
-    case BuiltinType::LongDouble:
-      llvm_unreachable("Builtin type needs extra local data!");
-      // Fall through, if the impossible happens.
-        
-    case BuiltinType::NullPtr:
-    case BuiltinType::Overload:
-    case BuiltinType::Dependent:
-    case BuiltinType::BoundMember:
-    case BuiltinType::UnknownAny:
-    case BuiltinType::ARCUnbridgedCast:
-    case BuiltinType::ObjCId:
-    case BuiltinType::ObjCClass:
-    case BuiltinType::ObjCSel:
-      return TST_unspecified;
-    }
+  switch (getTypePtr()->getKind()) {
+  case BuiltinType::Void:
+    return TST_void;
+  case BuiltinType::Bool:
+    return TST_bool;
+  case BuiltinType::Char_U:
+  case BuiltinType::Char_S:
+    return TST_char;
+  case BuiltinType::Char16:
+    return TST_char16;
+  case BuiltinType::Char32:
+    return TST_char32;
+  case BuiltinType::WChar_S:
+  case BuiltinType::WChar_U:
+    return TST_wchar;
+  case BuiltinType::UChar:
+  case BuiltinType::UShort:
+  case BuiltinType::UInt:
+  case BuiltinType::ULong:
+  case BuiltinType::ULongLong:
+  case BuiltinType::UInt128:
+  case BuiltinType::SChar:
+  case BuiltinType::Short:
+  case BuiltinType::Int:
+  case BuiltinType::Long:
+  case BuiltinType::LongLong:
+  case BuiltinType::Int128:
+  case BuiltinType::Half:
+  case BuiltinType::Float:
+  case BuiltinType::Double:
+  case BuiltinType::LongDouble:
+  case BuiltinType::Float128:
+    llvm_unreachable("Builtin type needs extra local data!");
+    // Fall through, if the impossible happens.
+      
+  case BuiltinType::NullPtr:
+  case BuiltinType::Overload:
+  case BuiltinType::Dependent:
+  case BuiltinType::BoundMember:
+  case BuiltinType::UnknownAny:
+  case BuiltinType::ARCUnbridgedCast:
+  case BuiltinType::PseudoObject:
+  case BuiltinType::ObjCId:
+  case BuiltinType::ObjCClass:
+  case BuiltinType::ObjCSel:
+#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
+  case BuiltinType::Id:
+#include "clang/Basic/OpenCLImageTypes.def"
+  case BuiltinType::OCLSampler:
+  case BuiltinType::OCLEvent:
+  case BuiltinType::OCLClkEvent:
+  case BuiltinType::OCLQueue:
+  case BuiltinType::OCLReserveID:
+  case BuiltinType::BuiltinFn:
+  case BuiltinType::OMPArraySection:
+    return TST_unspecified;
   }
-  
-  return TST_unspecified;
+
+  llvm_unreachable("Invalid BuiltinType Kind!");
 }
 
 TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
-  while (ParenTypeLoc* PTL = dyn_cast<ParenTypeLoc>(&TL))
-    TL = PTL->getInnerLoc();
+  while (ParenTypeLoc PTL = TL.getAs<ParenTypeLoc>())
+    TL = PTL.getInnerLoc();
   return TL;
 }
 
+SourceLocation TypeLoc::findNullabilityLoc() const {
+  if (auto attributedLoc = getAs<AttributedTypeLoc>()) {
+    if (attributedLoc.getAttrKind() == AttributedType::attr_nullable ||
+        attributedLoc.getAttrKind() == AttributedType::attr_nonnull ||
+        attributedLoc.getAttrKind() == AttributedType::attr_null_unspecified)
+      return attributedLoc.getAttrNameLoc();
+  }
+
+  return SourceLocation();
+}
+
+TypeLoc TypeLoc::findExplicitQualifierLoc() const {
+  // Qualified types.
+  if (auto qual = getAs<QualifiedTypeLoc>())
+    return qual;
+
+  TypeLoc loc = IgnoreParens();
+
+  // Attributed types.
+  if (auto attr = loc.getAs<AttributedTypeLoc>()) {
+    if (attr.isQualifier()) return attr;
+    return attr.getModifiedLoc().findExplicitQualifierLoc();
+  }
+
+  // C11 _Atomic types.
+  if (auto atomic = loc.getAs<AtomicTypeLoc>()) {
+    return atomic;
+  }
+
+  return TypeLoc();
+}
+
+void ObjCTypeParamTypeLoc::initializeLocal(ASTContext &Context,
+                                           SourceLocation Loc) {
+  setNameLoc(Loc);
+  if (!getNumProtocols()) return;
+
+  setProtocolLAngleLoc(Loc);
+  setProtocolRAngleLoc(Loc);
+  for (unsigned i = 0, e = getNumProtocols(); i != e; ++i)
+    setProtocolLoc(i, Loc);
+}
+
+void ObjCObjectTypeLoc::initializeLocal(ASTContext &Context, 
+                                        SourceLocation Loc) {
+  setHasBaseTypeAsWritten(true);
+  setTypeArgsLAngleLoc(Loc);
+  setTypeArgsRAngleLoc(Loc);
+  for (unsigned i = 0, e = getNumTypeArgs(); i != e; ++i) {
+    setTypeArgTInfo(i, 
+                   Context.getTrivialTypeSourceInfo(
+                     getTypePtr()->getTypeArgsAsWritten()[i], Loc));
+  }
+  setProtocolLAngleLoc(Loc);
+  setProtocolRAngleLoc(Loc);
+  for (unsigned i = 0, e = getNumProtocols(); i != e; ++i)
+    setProtocolLoc(i, Loc);
+}
+
+void TypeOfTypeLoc::initializeLocal(ASTContext &Context,
+                                       SourceLocation Loc) {
+  TypeofLikeTypeLoc<TypeOfTypeLoc, TypeOfType, TypeOfTypeLocInfo>
+      ::initializeLocal(Context, Loc);
+  this->getLocalData()->UnderlyingTInfo = Context.getTrivialTypeSourceInfo(
+      getUnderlyingType(), Loc);
+}
+
 void ElaboratedTypeLoc::initializeLocal(ASTContext &Context, 
                                         SourceLocation Loc) {
-  setKeywordLoc(Loc);
+  setElaboratedKeywordLoc(Loc);
   NestedNameSpecifierLocBuilder Builder;
   Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
   setQualifierLoc(Builder.getWithLocInContext(Context));
@@ -264,17 +432,17 @@ void ElaboratedTypeLoc::initializeLocal(ASTContext &Context,
 
 void DependentNameTypeLoc::initializeLocal(ASTContext &Context, 
                                            SourceLocation Loc) {
-  setKeywordLoc(Loc);
+  setElaboratedKeywordLoc(Loc);
   NestedNameSpecifierLocBuilder Builder;
   Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
   setQualifierLoc(Builder.getWithLocInContext(Context));
   setNameLoc(Loc);
 }
 
-void 
-DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context, 
+void
+DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context,
                                                         SourceLocation Loc) {
-  setKeywordLoc(Loc);
+  setElaboratedKeywordLoc(Loc);
   if (getTypePtr()->getQualifier()) {
     NestedNameSpecifierLocBuilder Builder;
     Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
@@ -282,8 +450,8 @@ DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context,
   } else {
     setQualifierLoc(NestedNameSpecifierLoc());
   }
-  
-  setNameLoc(Loc);
+  setTemplateKeywordLoc(Loc);
+  setTemplateNameLoc(Loc);
   setLAngleLoc(Loc);
   setRAngleLoc(Loc);
   TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(),
@@ -299,38 +467,43 @@ void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context,
   for (unsigned i = 0, e = NumArgs; i != e; ++i) {
     switch (Args[i].getKind()) {
     case TemplateArgument::Null: 
-    case TemplateArgument::Declaration:
+      llvm_unreachable("Impossible TemplateArgument");
+
     case TemplateArgument::Integral:
-    case TemplateArgument::Pack:
-    case TemplateArgument::Expression:
-      // FIXME: Can we do better for declarations and integral values?
+    case TemplateArgument::Declaration:
+    case TemplateArgument::NullPtr:
       ArgInfos[i] = TemplateArgumentLocInfo();
       break;
+
+    case TemplateArgument::Expression:
+      ArgInfos[i] = TemplateArgumentLocInfo(Args[i].getAsExpr());
+      break;
       
     case TemplateArgument::Type:
       ArgInfos[i] = TemplateArgumentLocInfo(
                           Context.getTrivialTypeSourceInfo(Args[i].getAsType(), 
                                                            Loc));
       break;
-        
+
     case TemplateArgument::Template:
     case TemplateArgument::TemplateExpansion: {
       NestedNameSpecifierLocBuilder Builder;
-      TemplateName Template = Args[i].getAsTemplate();
+      TemplateName Template = Args[i].getAsTemplateOrTemplatePattern();
       if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
         Builder.MakeTrivial(Context, DTN->getQualifier(), Loc);
       else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
         Builder.MakeTrivial(Context, QTN->getQualifier(), Loc);
-      
+
       ArgInfos[i] = TemplateArgumentLocInfo(
-                                           Builder.getWithLocInContext(Context),
-                                            Loc, 
-                                Args[i].getKind() == TemplateArgument::Template
-                                            ? SourceLocation()
-                                            : Loc);
+          Builder.getWithLocInContext(Context), Loc,
+          Args[i].getKind() == TemplateArgument::Template ? SourceLocation()
+                                                          : Loc);
+      break;
+    }
+
+    case TemplateArgument::Pack:
+      ArgInfos[i] = TemplateArgumentLocInfo();
       break;
-    }        
     }
   }
 }
-