]> granicus.if.org Git - clang/blobdiff - lib/AST/TemplateBase.cpp
[OPENMP] Initial support for 'task_reduction' clause.
[clang] / lib / AST / TemplateBase.cpp
index c3e2c4a7bba84a6ae0fc6fa02f6cbd6b92f051f1..e4998c37a4ef069234b68bbfa814c545aaf1c2e0 100644 (file)
@@ -33,12 +33,27 @@ using namespace clang;
 /// \param TemplArg the TemplateArgument instance to print.
 ///
 /// \param Out the raw_ostream instance to use for printing.
+///
+/// \param Policy the printing policy for EnumConstantDecl printing.
 static void printIntegral(const TemplateArgument &TemplArg,
-                          raw_ostream &Out) {
+                          raw_ostream &Out, const PrintingPolicy& Policy) {
   const ::clang::Type *T = TemplArg.getIntegralType().getTypePtr();
   const llvm::APSInt &Val = TemplArg.getAsIntegral();
 
-  if (T->isBooleanType()) {
+  if (const EnumType *ET = T->getAs<EnumType>()) {
+    for (const EnumConstantDecl* ECD : ET->getDecl()->enumerators()) {
+      // In Sema::CheckTemplateArugment, enum template arguments value are
+      // extended to the size of the integer underlying the enum type.  This
+      // may create a size difference between the enum value and template
+      // argument value, requiring isSameValue here instead of operator==.
+      if (llvm::APSInt::isSameValue(ECD->getInitVal(), Val)) {
+        ECD->printQualifiedName(Out, Policy);
+        return;
+      }
+    }
+  }
+
+  if (T->isBooleanType() && !Policy.MSVCFormatting) {
     Out << (Val.getBoolValue() ? "true" : "false");
   } else if (T->isCharType()) {
     const char Ch = Val.getZExtValue();
@@ -55,8 +70,8 @@ static void printIntegral(const TemplateArgument &TemplArg,
 //===----------------------------------------------------------------------===//
 
 TemplateArgument::TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value,
-                                   QualType Type)
-  : Kind(Integral) {
+                                   QualType Type) {
+  Integer.Kind = Integral;
   // Copy the APSInt value into our decomposed form.
   Integer.BitWidth = Value.getBitWidth();
   Integer.IsUnsigned = Value.isUnsigned();
@@ -73,15 +88,13 @@ TemplateArgument::TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value,
   Integer.Type = Type.getAsOpaquePtr();
 }
 
-TemplateArgument TemplateArgument::CreatePackCopy(ASTContext &Context,
-                                                  const TemplateArgument *Args,
-                                                  unsigned NumArgs) {
-  if (NumArgs == 0)
+TemplateArgument
+TemplateArgument::CreatePackCopy(ASTContext &Context,
+                                 ArrayRef<TemplateArgument> Args) {
+  if (Args.empty())
     return getEmptyPack();
-  
-  TemplateArgument *Storage = new (Context) TemplateArgument [NumArgs];
-  std::copy(Args, Args + NumArgs, Storage);
-  return TemplateArgument(Storage, NumArgs);
+
+  return TemplateArgument(Args.copy(Context));
 }
 
 bool TemplateArgument::isDependent() const {
@@ -90,7 +103,8 @@ bool TemplateArgument::isDependent() const {
     llvm_unreachable("Should not have a NULL template argument");
 
   case Type:
-    return getAsType()->isDependentType();
+    return getAsType()->isDependentType() ||
+           isa<PackExpansionType>(getAsType());
 
   case Template:
     return getAsTemplate().isDependent();
@@ -111,14 +125,13 @@ bool TemplateArgument::isDependent() const {
     return false;
 
   case Expression:
-    return (getAsExpr()->isTypeDependent() || getAsExpr()->isValueDependent());
+    return (getAsExpr()->isTypeDependent() || getAsExpr()->isValueDependent() ||
+            isa<PackExpansionExpr>(getAsExpr()));
 
   case Pack:
-    for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P) {
-      if (P->isDependent())
+    for (const auto &P : pack_elements())
+      if (P.isDependent())
         return true;
-    }
-
     return false;
   }
 
@@ -155,11 +168,9 @@ bool TemplateArgument::isInstantiationDependent() const {
     return getAsExpr()->isInstantiationDependent();
     
   case Pack:
-    for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P) {
-      if (P->isInstantiationDependent())
+    for (const auto &P : pack_elements())
+      if (P.isInstantiationDependent())
         return true;
-    }
-    
     return false;
   }
 
@@ -214,8 +225,8 @@ bool TemplateArgument::containsUnexpandedParameterPack() const {
     break;
 
   case Pack:
-    for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P)
-      if (P->containsUnexpandedParameterPack())
+    for (const auto &P : pack_elements())
+      if (P.containsUnexpandedParameterPack())
         return true;
 
     break;
@@ -225,17 +236,42 @@ bool TemplateArgument::containsUnexpandedParameterPack() const {
 }
 
 Optional<unsigned> TemplateArgument::getNumTemplateExpansions() const {
-  assert(Kind == TemplateExpansion);
+  assert(getKind() == TemplateExpansion);
   if (TemplateArg.NumExpansions)
     return TemplateArg.NumExpansions - 1;
   
   return None; 
 }
 
+QualType TemplateArgument::getNonTypeTemplateArgumentType() const {
+  switch (getKind()) {
+  case TemplateArgument::Null:
+  case TemplateArgument::Type:
+  case TemplateArgument::Template:
+  case TemplateArgument::TemplateExpansion:
+  case TemplateArgument::Pack:
+    return QualType();
+
+  case TemplateArgument::Integral:
+    return getIntegralType();
+
+  case TemplateArgument::Expression:
+    return getAsExpr()->getType();
+
+  case TemplateArgument::Declaration:
+    return getParamTypeForDecl();
+
+  case TemplateArgument::NullPtr:
+    return getNullPtrType();
+  }
+
+  llvm_unreachable("Invalid TemplateArgument Kind!");
+}
+
 void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
                                const ASTContext &Context) const {
-  ID.AddInteger(Kind);
-  switch (Kind) {
+  ID.AddInteger(getKind());
+  switch (getKind()) {
   case Null:
     break;
 
@@ -243,8 +279,12 @@ void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
     getAsType().Profile(ID);
     break;
 
+  case NullPtr:
+    getNullPtrType().Profile(ID);
+    break;
+
   case Declaration:
-    ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0);
+    ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : nullptr);
     break;
 
   case Template:
@@ -291,11 +331,10 @@ bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
   case Template:
   case TemplateExpansion:
   case NullPtr:
-    return TypeOrValue == Other.TypeOrValue;
+    return TypeOrValue.V == Other.TypeOrValue.V;
 
   case Declaration:
-    return getAsDecl() == Other.getAsDecl() && 
-           isDeclForReferenceParam() && Other.isDeclForReferenceParam();
+    return getAsDecl() == Other.getAsDecl();
 
   case Integral:
     return getIntegralType() == Other.getIntegralType() &&
@@ -341,7 +380,7 @@ void TemplateArgument::print(const PrintingPolicy &Policy,
                              raw_ostream &Out) const {
   switch (getKind()) {
   case Null:
-    Out << "<no value>";
+    Out << "(no value)";
     break;
     
   case Type: {
@@ -358,7 +397,7 @@ void TemplateArgument::print(const PrintingPolicy &Policy,
       // FIXME: distinguish between pointer and reference args?
       ND->printQualifiedName(Out);
     } else {
-      Out << "<anonymous>";
+      Out << "(anonymous)";
     }
     break;
   }
@@ -377,39 +416,43 @@ void TemplateArgument::print(const PrintingPolicy &Policy,
     break;
       
   case Integral: {
-    printIntegral(*this, Out);
+    printIntegral(*this, Out, Policy);
     break;
   }
     
   case Expression:
-    getAsExpr()->printPretty(Out, 0, Policy);
+    getAsExpr()->printPretty(Out, nullptr, Policy);
     break;
     
   case Pack:
     Out << "<";
     bool First = true;
-    for (TemplateArgument::pack_iterator P = pack_begin(), PEnd = pack_end();
-         P != PEnd; ++P) {
+    for (const auto &P : pack_elements()) {
       if (First)
         First = false;
       else
         Out << ", ";
       
-      P->print(Policy, Out);
+      P.print(Policy, Out);
     }
     Out << ">";
     break;        
   }
 }
 
+void TemplateArgument::dump(raw_ostream &Out) const {
+  LangOptions LO; // FIXME! see also TemplateName::dump().
+  LO.CPlusPlus = true;
+  LO.Bool = true;
+  print(PrintingPolicy(LO), Out);
+}
+
+LLVM_DUMP_METHOD void TemplateArgument::dump() const { dump(llvm::errs()); }
+
 //===----------------------------------------------------------------------===//
 // TemplateArgumentLoc Implementation
 //===----------------------------------------------------------------------===//
 
-TemplateArgumentLocInfo::TemplateArgumentLocInfo() {
-  memset((void*)this, 0, sizeof(TemplateArgumentLocInfo));
-}
-
 SourceRange TemplateArgumentLoc::getSourceRange() const {
   switch (Argument.getKind()) {
   case TemplateArgument::Expression:
@@ -450,68 +493,6 @@ SourceRange TemplateArgumentLoc::getSourceRange() const {
   llvm_unreachable("Invalid TemplateArgument Kind!");
 }
 
-TemplateArgumentLoc TemplateArgumentLoc::getPackExpansionPattern(
-    SourceLocation &Ellipsis, Optional<unsigned> &NumExpansions,
-    ASTContext &Context) const {
-  assert(Argument.isPackExpansion());
-  
-  switch (Argument.getKind()) {
-  case TemplateArgument::Type: {
-    // FIXME: We shouldn't ever have to worry about missing
-    // type-source info!
-    TypeSourceInfo *ExpansionTSInfo = getTypeSourceInfo();
-    if (!ExpansionTSInfo)
-      ExpansionTSInfo = Context.getTrivialTypeSourceInfo(
-                                                     getArgument().getAsType(),
-                                                         Ellipsis);
-    PackExpansionTypeLoc Expansion =
-        ExpansionTSInfo->getTypeLoc().castAs<PackExpansionTypeLoc>();
-    Ellipsis = Expansion.getEllipsisLoc();
-    
-    TypeLoc Pattern = Expansion.getPatternLoc();
-    NumExpansions = Expansion.getTypePtr()->getNumExpansions();
-    
-    // FIXME: This is horrible. We know where the source location data is for
-    // the pattern, and we have the pattern's type, but we are forced to copy
-    // them into an ASTContext because TypeSourceInfo bundles them together
-    // and TemplateArgumentLoc traffics in TypeSourceInfo pointers.
-    TypeSourceInfo *PatternTSInfo
-      = Context.CreateTypeSourceInfo(Pattern.getType(),
-                                     Pattern.getFullDataSize());
-    memcpy(PatternTSInfo->getTypeLoc().getOpaqueData(), 
-           Pattern.getOpaqueData(), Pattern.getFullDataSize());
-    return TemplateArgumentLoc(TemplateArgument(Pattern.getType()),
-                               PatternTSInfo);
-  }
-      
-  case TemplateArgument::Expression: {
-    PackExpansionExpr *Expansion
-      = cast<PackExpansionExpr>(Argument.getAsExpr());
-    Expr *Pattern = Expansion->getPattern();
-    Ellipsis = Expansion->getEllipsisLoc();
-    NumExpansions = Expansion->getNumExpansions();
-    return TemplateArgumentLoc(Pattern, Pattern);
-  }
-
-  case TemplateArgument::TemplateExpansion:
-    Ellipsis = getTemplateEllipsisLoc();
-    NumExpansions = Argument.getNumTemplateExpansions();
-    return TemplateArgumentLoc(Argument.getPackExpansionPattern(),
-                               getTemplateQualifierLoc(),
-                               getTemplateNameLoc());
-    
-  case TemplateArgument::Declaration:
-  case TemplateArgument::NullPtr:
-  case TemplateArgument::Template:
-  case TemplateArgument::Integral:
-  case TemplateArgument::Pack:
-  case TemplateArgument::Null:
-    return TemplateArgumentLoc();
-  }
-
-  llvm_unreachable("Invalid TemplateArgument Kind!");
-}
-
 const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
                                            const TemplateArgument &Arg) {
   switch (Arg.getKind()) {
@@ -547,7 +528,7 @@ const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
     LangOptions LangOpts;
     LangOpts.CPlusPlus = true;
     PrintingPolicy Policy(LangOpts);
-    Arg.getAsExpr()->printPretty(OS, 0, Policy);
+    Arg.getAsExpr()->printPretty(OS, nullptr, Policy);
     return DB << OS.str();
   }
       
@@ -569,92 +550,67 @@ const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
 const ASTTemplateArgumentListInfo *
 ASTTemplateArgumentListInfo::Create(ASTContext &C,
                                     const TemplateArgumentListInfo &List) {
-  std::size_t size = ASTTemplateArgumentListInfo::sizeFor(List.size());
-  void *Mem = C.Allocate(size, llvm::alignOf<ASTTemplateArgumentListInfo>());
-  ASTTemplateArgumentListInfo *TAI = new (Mem) ASTTemplateArgumentListInfo();
-  TAI->initializeFrom(List);
-  return TAI;
+  std::size_t size = totalSizeToAlloc<TemplateArgumentLoc>(List.size());
+  void *Mem = C.Allocate(size, alignof(ASTTemplateArgumentListInfo));
+  return new (Mem) ASTTemplateArgumentListInfo(List);
 }
 
-void ASTTemplateArgumentListInfo::initializeFrom(
-                                      const TemplateArgumentListInfo &Info) {
+ASTTemplateArgumentListInfo::ASTTemplateArgumentListInfo(
+    const TemplateArgumentListInfo &Info) {
   LAngleLoc = Info.getLAngleLoc();
   RAngleLoc = Info.getRAngleLoc();
   NumTemplateArgs = Info.size();
 
-  TemplateArgumentLoc *ArgBuffer = getTemplateArgs();
+  TemplateArgumentLoc *ArgBuffer = getTrailingObjects<TemplateArgumentLoc>();
   for (unsigned i = 0; i != NumTemplateArgs; ++i)
     new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]);
 }
 
-void ASTTemplateArgumentListInfo::initializeFrom(
-                                          const TemplateArgumentListInfo &Info,
-                                                  bool &Dependent, 
-                                                  bool &InstantiationDependent,
-                                       bool &ContainsUnexpandedParameterPack) {
+void ASTTemplateKWAndArgsInfo::initializeFrom(
+    SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info,
+    TemplateArgumentLoc *OutArgArray) {
+  this->TemplateKWLoc = TemplateKWLoc;
+  LAngleLoc = Info.getLAngleLoc();
+  RAngleLoc = Info.getRAngleLoc();
+  NumTemplateArgs = Info.size();
+
+  for (unsigned i = 0; i != NumTemplateArgs; ++i)
+    new (&OutArgArray[i]) TemplateArgumentLoc(Info[i]);
+}
+
+void ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc) {
+  assert(TemplateKWLoc.isValid());
+  LAngleLoc = SourceLocation();
+  RAngleLoc = SourceLocation();
+  this->TemplateKWLoc = TemplateKWLoc;
+  NumTemplateArgs = 0;
+}
+
+void ASTTemplateKWAndArgsInfo::initializeFrom(
+    SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info,
+    TemplateArgumentLoc *OutArgArray, bool &Dependent,
+    bool &InstantiationDependent, bool &ContainsUnexpandedParameterPack) {
+  this->TemplateKWLoc = TemplateKWLoc;
   LAngleLoc = Info.getLAngleLoc();
   RAngleLoc = Info.getRAngleLoc();
   NumTemplateArgs = Info.size();
 
-  TemplateArgumentLoc *ArgBuffer = getTemplateArgs();
   for (unsigned i = 0; i != NumTemplateArgs; ++i) {
     Dependent = Dependent || Info[i].getArgument().isDependent();
-    InstantiationDependent = InstantiationDependent || 
+    InstantiationDependent = InstantiationDependent ||
                              Info[i].getArgument().isInstantiationDependent();
-    ContainsUnexpandedParameterPack 
-      = ContainsUnexpandedParameterPack || 
+    ContainsUnexpandedParameterPack =
+        ContainsUnexpandedParameterPack ||
         Info[i].getArgument().containsUnexpandedParameterPack();
 
-    new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]);
+    new (&OutArgArray[i]) TemplateArgumentLoc(Info[i]);
   }
 }
 
-void ASTTemplateArgumentListInfo::copyInto(
-                                      TemplateArgumentListInfo &Info) const {
+void ASTTemplateKWAndArgsInfo::copyInto(const TemplateArgumentLoc *ArgArray,
+                                        TemplateArgumentListInfo &Info) const {
   Info.setLAngleLoc(LAngleLoc);
   Info.setRAngleLoc(RAngleLoc);
   for (unsigned I = 0; I != NumTemplateArgs; ++I)
-    Info.addArgument(getTemplateArgs()[I]);
-}
-
-std::size_t ASTTemplateArgumentListInfo::sizeFor(unsigned NumTemplateArgs) {
-  return sizeof(ASTTemplateArgumentListInfo) +
-         sizeof(TemplateArgumentLoc) * NumTemplateArgs;
-}
-
-void
-ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc,
-                                         const TemplateArgumentListInfo &Info) {
-  Base::initializeFrom(Info);
-  setTemplateKeywordLoc(TemplateKWLoc);
-}
-
-void
-ASTTemplateKWAndArgsInfo
-::initializeFrom(SourceLocation TemplateKWLoc,
-                 const TemplateArgumentListInfo &Info,
-                 bool &Dependent,
-                 bool &InstantiationDependent,
-                 bool &ContainsUnexpandedParameterPack) {
-  Base::initializeFrom(Info, Dependent, InstantiationDependent,
-                       ContainsUnexpandedParameterPack);
-  setTemplateKeywordLoc(TemplateKWLoc);
-}
-
-void
-ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc) {
-  // No explicit template arguments, but template keyword loc is valid.
-  assert(TemplateKWLoc.isValid());
-  LAngleLoc = SourceLocation();
-  RAngleLoc = SourceLocation();
-  NumTemplateArgs = 0;
-  setTemplateKeywordLoc(TemplateKWLoc);
-}
-
-std::size_t
-ASTTemplateKWAndArgsInfo::sizeFor(unsigned NumTemplateArgs) {
-  // Add space for the template keyword location.
-  // FIXME: There's room for this in the padding before the template args in
-  //        64-bit builds.
-  return Base::sizeFor(NumTemplateArgs) + sizeof(SourceLocation);
+    Info.addArgument(ArgArray[I]);
 }