static bool IsStdVector(QualType T) {
  const TemplateSpecializationType *TS = T->getAs<TemplateSpecializationType>();
  if (!TS)
    return false;

  TemplateName TM = TS->getTemplateName();
  TemplateDecl *TD = TM.getAsTemplateDecl();

  if (!TD || !InNamespace(TD, "std"))
    return false;

  return TD->getName() == "vector";
}
Example #2
0
void USRGenerator::VisitTemplateName(TemplateName Name) {
  if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
    if (TemplateTemplateParmDecl *TTP
                              = dyn_cast<TemplateTemplateParmDecl>(Template)) {
      Out << 't' << TTP->getDepth() << '.' << TTP->getIndex();
      return;
    }
    
    Visit(Template);
    return;
  }
  
  // FIXME: Visit dependent template names.
}
Example #3
0
void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
                               const ASTContext &Context) const {
  ID.AddInteger(Kind);
  switch (Kind) {
  case Null:
    break;

  case Type:
    getAsType().Profile(ID);
    break;

  case Declaration:
    ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0);
    break;

  case Template:
  case TemplateExpansion: {
    TemplateName Template = getAsTemplateOrTemplatePattern();
    if (TemplateTemplateParmDecl *TTP
          = dyn_cast_or_null<TemplateTemplateParmDecl>(
                                                Template.getAsTemplateDecl())) {
      ID.AddBoolean(true);
      ID.AddInteger(TTP->getDepth());
      ID.AddInteger(TTP->getPosition());
      ID.AddBoolean(TTP->isParameterPack());
    } else {
      ID.AddBoolean(false);
      ID.AddPointer(Context.getCanonicalTemplateName(Template)
                                                          .getAsVoidPointer());
    }
    break;
  }

  case Integral:
    getAsIntegral().Profile(ID);
    getIntegralType().Profile(ID);
    break;

  case Expression:
    getAsExpr()->Profile(ID, Context, true);
    break;

  case Pack:
    ID.AddInteger(Args.NumArgs);
    for (unsigned I = 0; I != Args.NumArgs; ++I)
      Args.Args[I].Profile(ID, Context);
  }
}
Example #4
0
void ODRHash::AddTemplateName(TemplateName Name) {
  auto Kind = Name.getKind();
  ID.AddInteger(Kind);

  switch (Kind) {
  case TemplateName::Template:
    AddDecl(Name.getAsTemplateDecl());
    break;
  // TODO: Support these cases.
  case TemplateName::OverloadedTemplate:
  case TemplateName::QualifiedTemplate:
  case TemplateName::DependentTemplate:
  case TemplateName::SubstTemplateTemplateParm:
  case TemplateName::SubstTemplateTemplateParmPack:
    break;
  }
}
Example #5
0
void TemplateArgToInt::handleTemplateSpecializationTypeLoc(
       const TemplateSpecializationTypeLoc &TLoc)
{
  const Type *Ty = TLoc.getTypePtr();
  const TemplateSpecializationType *TST = 
    Ty->getAs<TemplateSpecializationType>();
  TemplateName TplName = TST->getTemplateName();
  const TemplateDecl *TplD = TplName.getAsTemplateDecl();

  TemplateParameterIdxSet *InvalidIdx = 
    DeclToParamIdx[dyn_cast<TemplateDecl>(TplD->getCanonicalDecl())];
  if (!InvalidIdx)
    return;
  for (unsigned I = 0; I < TLoc.getNumArgs(); ++I) {
    if (!InvalidIdx->count(I))
      handleOneTemplateArgumentLoc(TLoc.getArgLoc(I));
  }
}
const NamedDecl *ReduceClassTemplateParameter::getNamedDecl(
        const TemplateArgument &Arg)
{
  if (!Arg.isInstantiationDependent())
    return NULL;

  TemplateArgument::ArgKind K = Arg.getKind();
  switch (K) {
  case TemplateArgument::Expression: {
    const Expr *E = Arg.getAsExpr();
    if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
      return dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl());
    }
    else {
      return NULL;
    }
  }

  case TemplateArgument::Template: {
    TemplateName TmplName = Arg.getAsTemplate();
    TransAssert((TmplName.getKind() == TemplateName::Template) &&
                "Invalid TemplateName Kind!");
    return TmplName.getAsTemplateDecl();
  }

  case TemplateArgument::Type: {
    const Type *Ty = Arg.getAsType().getTypePtr();
    if (const TemplateTypeParmType *TmplTy = 
        dyn_cast<TemplateTypeParmType>(Ty)) {
      return TmplTy->getDecl();
    }
    else {
      return NULL;
    }
  }
  
  default:
    return NULL;
  }

  TransAssert(0 && "Unreachable code!");
  return NULL;
}
Example #7
0
bool CXXRecordDecl::FindOrdinaryMemberInDependentClasses(
    const CXXBaseSpecifier *Specifier, CXXBasePath &Path,
    DeclarationName Name) {
  const TemplateSpecializationType *TST =
      Specifier->getType()->getAs<TemplateSpecializationType>();
  if (!TST) {
    auto *RT = Specifier->getType()->getAs<RecordType>();
    if (!RT)
      return false;
    return findOrdinaryMember(RT->getDecl(), Path, Name);
  }
  TemplateName TN = TST->getTemplateName();
  const auto *TD = dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl());
  if (!TD)
    return false;
  CXXRecordDecl *RD = TD->getTemplatedDecl();
  if (!RD)
    return false;
  return findOrdinaryMember(RD, Path, Name);
}
bool RemoveNamespaceRewriteVisitor::VisitTemplateSpecializationTypeLoc(
       TemplateSpecializationTypeLoc TSPLoc)
{
  const Type *Ty = TSPLoc.getTypePtr();
  const TemplateSpecializationType *TST =
    dyn_cast<TemplateSpecializationType>(Ty);
  TransAssert(TST && "Bad TemplateSpecializationType!");

  TemplateName TplName = TST->getTemplateName();
  const TemplateDecl *TplD = TplName.getAsTemplateDecl();
  TransAssert(TplD && "Invalid TemplateDecl!");
  NamedDecl *ND = TplD->getTemplatedDecl();
  // in some cases, ND could be NULL, e.g., the
  // template template parameter code below:
  // template<template<class> class BBB>
  // struct AAA {
  //   template <class T>
  //   struct CCC {
  //     static BBB<T> a;
  //   };
  // };
  // where we don't know BBB
  if (!ND)
    return true;

  const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(ND);
  if (!CXXRD)
    return true;

  std::string Name;
  if (ConsumerInstance->getNewName(CXXRD, Name)) {
    SourceLocation LocStart = TSPLoc.getTemplateNameLoc();
    ConsumerInstance->TheRewriter.ReplaceText(
      LocStart, CXXRD->getNameAsString().size(), Name);
  }

  return true;
}
Example #9
0
bool CXXBasePaths::lookupInBases(ASTContext &Context,
                                 const CXXRecordDecl *Record,
                                 CXXRecordDecl::BaseMatchesCallback BaseMatches,
                                 bool LookupInDependent) {
  bool FoundPath = false;

  // The access of the path down to this record.
  AccessSpecifier AccessToHere = ScratchPath.Access;
  bool IsFirstStep = ScratchPath.empty();

  for (const auto &BaseSpec : Record->bases()) {
    // Find the record of the base class subobjects for this type.
    QualType BaseType =
        Context.getCanonicalType(BaseSpec.getType()).getUnqualifiedType();

    // C++ [temp.dep]p3:
    //   In the definition of a class template or a member of a class template,
    //   if a base class of the class template depends on a template-parameter,
    //   the base class scope is not examined during unqualified name lookup 
    //   either at the point of definition of the class template or member or 
    //   during an instantiation of the class tem- plate or member.
    if (!LookupInDependent && BaseType->isDependentType())
      continue;
    
    // Determine whether we need to visit this base class at all,
    // updating the count of subobjects appropriately.
    std::pair<bool, unsigned>& Subobjects = ClassSubobjects[BaseType];
    bool VisitBase = true;
    bool SetVirtual = false;
    if (BaseSpec.isVirtual()) {
      VisitBase = !Subobjects.first;
      Subobjects.first = true;
      if (isDetectingVirtual() && DetectedVirtual == nullptr) {
        // If this is the first virtual we find, remember it. If it turns out
        // there is no base path here, we'll reset it later.
        DetectedVirtual = BaseType->getAs<RecordType>();
        SetVirtual = true;
      }
    } else
      ++Subobjects.second;
    
    if (isRecordingPaths()) {
      // Add this base specifier to the current path.
      CXXBasePathElement Element;
      Element.Base = &BaseSpec;
      Element.Class = Record;
      if (BaseSpec.isVirtual())
        Element.SubobjectNumber = 0;
      else
        Element.SubobjectNumber = Subobjects.second;
      ScratchPath.push_back(Element);

      // Calculate the "top-down" access to this base class.
      // The spec actually describes this bottom-up, but top-down is
      // equivalent because the definition works out as follows:
      // 1. Write down the access along each step in the inheritance
      //    chain, followed by the access of the decl itself.
      //    For example, in
      //      class A { public: int foo; };
      //      class B : protected A {};
      //      class C : public B {};
      //      class D : private C {};
      //    we would write:
      //      private public protected public
      // 2. If 'private' appears anywhere except far-left, access is denied.
      // 3. Otherwise, overall access is determined by the most restrictive
      //    access in the sequence.
      if (IsFirstStep)
        ScratchPath.Access = BaseSpec.getAccessSpecifier();
      else
        ScratchPath.Access = CXXRecordDecl::MergeAccess(AccessToHere, 
                                                 BaseSpec.getAccessSpecifier());
    }
    
    // Track whether there's a path involving this specific base.
    bool FoundPathThroughBase = false;
    
    if (BaseMatches(&BaseSpec, ScratchPath)) {
      // We've found a path that terminates at this base.
      FoundPath = FoundPathThroughBase = true;
      if (isRecordingPaths()) {
        // We have a path. Make a copy of it before moving on.
        Paths.push_back(ScratchPath);
      } else if (!isFindingAmbiguities()) {
        // We found a path and we don't care about ambiguities;
        // return immediately.
        return FoundPath;
      }
    } else if (VisitBase) {
      CXXRecordDecl *BaseRecord;
      if (LookupInDependent) {
        BaseRecord = nullptr;
        const TemplateSpecializationType *TST =
            BaseSpec.getType()->getAs<TemplateSpecializationType>();
        if (!TST) {
          if (auto *RT = BaseSpec.getType()->getAs<RecordType>())
            BaseRecord = cast<CXXRecordDecl>(RT->getDecl());
        } else {
          TemplateName TN = TST->getTemplateName();
          if (auto *TD =
                  dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl()))
            BaseRecord = TD->getTemplatedDecl();
        }
        if (BaseRecord) {
          if (!BaseRecord->hasDefinition() ||
              VisitedDependentRecords.count(BaseRecord)) {
            BaseRecord = nullptr;
          } else {
            VisitedDependentRecords.insert(BaseRecord);
          }
        }
      } else {
        BaseRecord = cast<CXXRecordDecl>(
            BaseSpec.getType()->castAs<RecordType>()->getDecl());
      }
      if (BaseRecord &&
          lookupInBases(Context, BaseRecord, BaseMatches, LookupInDependent)) {
        // C++ [class.member.lookup]p2:
        //   A member name f in one sub-object B hides a member name f in
        //   a sub-object A if A is a base class sub-object of B. Any
        //   declarations that are so hidden are eliminated from
        //   consideration.
        
        // There is a path to a base class that meets the criteria. If we're 
        // not collecting paths or finding ambiguities, we're done.
        FoundPath = FoundPathThroughBase = true;
        if (!isFindingAmbiguities())
          return FoundPath;
      }
    }
    
    // Pop this base specifier off the current path (if we're
    // collecting paths).
    if (isRecordingPaths()) {
      ScratchPath.pop_back();
    }

    // If we set a virtual earlier, and this isn't a path, forget it again.
    if (SetVirtual && !FoundPathThroughBase) {
      DetectedVirtual = nullptr;
    }
  }

  // Reset the scratch path access.
  ScratchPath.Access = AccessToHere;
  
  return FoundPath;
}