Пример #1
0
bool Sema::DiagnoseUnexpandedParameterPack(const DeclarationNameInfo &NameInfo,
                                         UnexpandedParameterPackContext UPPC) {
  // C++0x [temp.variadic]p5:
  //   An appearance of a name of a parameter pack that is not expanded is
  //   ill-formed.
  switch (NameInfo.getName().getNameKind()) {
  case DeclarationName::Identifier:
  case DeclarationName::ObjCZeroArgSelector:
  case DeclarationName::ObjCOneArgSelector:
  case DeclarationName::ObjCMultiArgSelector:
  case DeclarationName::CXXOperatorName:
  case DeclarationName::CXXLiteralOperatorName:
  case DeclarationName::CXXUsingDirective:
    return false;

  case DeclarationName::CXXConstructorName:
  case DeclarationName::CXXDestructorName:
  case DeclarationName::CXXConversionFunctionName:
    // FIXME: We shouldn't need this null check!
    if (TypeSourceInfo *TSInfo = NameInfo.getNamedTypeInfo())
      return DiagnoseUnexpandedParameterPack(NameInfo.getLoc(), TSInfo, UPPC);

    if (!NameInfo.getName().getCXXNameType()->containsUnexpandedParameterPack())
      return false;

    break;
  }

  SmallVector<UnexpandedParameterPack, 2> Unexpanded;
  CollectUnexpandedParameterPacksVisitor(Unexpanded)
    .TraverseType(NameInfo.getName().getCXXNameType());
  assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
  return DiagnoseUnexpandedParameterPacks(NameInfo.getLoc(), UPPC, Unexpanded);
}
Пример #2
0
bool RewriteUtils::replaceCXXDestructorDeclName(
       const CXXDestructorDecl *DtorDecl,
       const std::string &Name)
{
  SourceLocation StartLoc = DtorDecl->getLocation();
  const char *StartBuf = SrcManager->getCharacterData(StartLoc);
  TransAssert((*StartBuf == '~') && "Invalid Destructor Location");
  // FIXME: it's quite ugly, better to use clang's Lexer
  unsigned Off = 0;
  StartBuf++;
  while (isspace(*StartBuf)) {
    StartBuf++;
    Off++;
  }

  std::string DName = DtorDecl->getNameAsString();
  DeclarationNameInfo NameInfo = DtorDecl->getNameInfo();
  DeclarationName DeclName = NameInfo.getName();
  const Type *Ty = DeclName.getCXXNameType().getTypePtr();
  size_t NameLen;
  if (Ty->getTypeClass() == Type::InjectedClassName) {
    const CXXRecordDecl *CXXRD = Ty->getAsCXXRecordDecl();
    std::string RDName = CXXRD->getNameAsString();
    NameLen = DName.find(RDName);
    TransAssert((NameLen != std::string::npos) && 
                "Cannot find RecordDecl Name!");
    NameLen += RDName.length();
  }
  else {
    NameLen = DName.length();
  }
  NameLen += Off;
 
  return !TheRewriter->ReplaceText(StartLoc,
                                   NameLen,
                                   "~" + Name);
}
Пример #3
0
bool RewriteUtils::replaceFunctionDeclName(const FunctionDecl *FD,
                                      const std::string &NameStr)
{
  // We cannot naively use FD->getNameAsString() here. 
  // For example, for a template class
  // template<typename T>
  // class SomeClass {
  // public:
  //   SomeClass() {}
  // };
  // applying getNameAsString() on SomeClass() gives us SomeClass<T>.

  DeclarationNameInfo NameInfo = FD->getNameInfo();
  DeclarationName DeclName = NameInfo.getName();
  DeclarationName::NameKind K = DeclName.getNameKind();
  TransAssert((K != DeclarationName::CXXDestructorName) &&
              "Cannot rename CXXDestructorName here!");

  std::string FDName = FD->getNameAsString();
  size_t FDNameLen = FD->getNameAsString().length();
  if (K == DeclarationName::CXXConstructorName) {
    const Type *Ty = DeclName.getCXXNameType().getTypePtr();
    if (Ty->getTypeClass() == Type::InjectedClassName) {
      const CXXRecordDecl *CXXRD = Ty->getAsCXXRecordDecl();
      std::string RDName = CXXRD->getNameAsString();
      FDNameLen = FDName.find(RDName);
      TransAssert((FDNameLen != std::string::npos) && 
                  "Cannot find RecordDecl Name!");
      FDNameLen += RDName.length();
    }
  }

  return !TheRewriter->ReplaceText(NameInfo.getLoc(),
                                   FDNameLen,
                                   NameStr);
}
Пример #4
0
ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
                                         CXXScopeSpec &ScopeSpec,
                                         const DeclarationNameInfo &Id) {
  LookupResult Lookup(*this, Id, LookupOrdinaryName);
  LookupParsedName(Lookup, CurScope, &ScopeSpec, true);

  if (Lookup.isAmbiguous())
    return ExprError();

  VarDecl *VD;
  if (!Lookup.isSingleResult()) {
    VarDeclFilterCCC Validator(*this);
    if (TypoCorrection Corrected = CorrectTypo(Id, LookupOrdinaryName, CurScope,
                                               0, Validator)) {
      diagnoseTypo(Corrected,
                   PDiag(Lookup.empty()? diag::err_undeclared_var_use_suggest
                                       : diag::err_omp_expected_var_arg_suggest)
                     << Id.getName());
      VD = Corrected.getCorrectionDeclAs<VarDecl>();
    } else {
      Diag(Id.getLoc(), Lookup.empty() ? diag::err_undeclared_var_use
                                       : diag::err_omp_expected_var_arg)
          << Id.getName();
      return ExprError();
    }
  } else {
    if (!(VD = Lookup.getAsSingle<VarDecl>())) {
      Diag(Id.getLoc(), diag::err_omp_expected_var_arg)
        << Id.getName();
      Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
      return ExprError();
    }
  }
  Lookup.suppressDiagnostics();

  // OpenMP [2.9.2, Syntax, C/C++]
  //   Variables must be file-scope, namespace-scope, or static block-scope.
  if (!VD->hasGlobalStorage()) {
    Diag(Id.getLoc(), diag::err_omp_global_var_arg)
      << getOpenMPDirectiveName(OMPD_threadprivate)
      << !VD->isStaticLocal();
    bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
                  VarDecl::DeclarationOnly;
    Diag(VD->getLocation(),
         IsDecl ? diag::note_previous_decl : diag::note_defined_here) << VD;
    return ExprError();
  }

  VarDecl *CanonicalVD = VD->getCanonicalDecl();
  NamedDecl *ND = cast<NamedDecl>(CanonicalVD);
  // OpenMP [2.9.2, Restrictions, C/C++, p.2]
  //   A threadprivate directive for file-scope variables must appear outside
  //   any definition or declaration.
  if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
      !getCurLexicalContext()->isTranslationUnit()) {
    Diag(Id.getLoc(), diag::err_omp_var_scope)
      << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
    bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
                  VarDecl::DeclarationOnly;
    Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
                                     diag::note_defined_here) << VD;
    return ExprError();
  }
  // OpenMP [2.9.2, Restrictions, C/C++, p.3]
  //   A threadprivate directive for static class member variables must appear
  //   in the class definition, in the same scope in which the member
  //   variables are declared.
  if (CanonicalVD->isStaticDataMember() &&
      !CanonicalVD->getDeclContext()->Equals(getCurLexicalContext())) {
    Diag(Id.getLoc(), diag::err_omp_var_scope)
      << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
    bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
                  VarDecl::DeclarationOnly;
    Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
                                     diag::note_defined_here) << VD;
    return ExprError();
  }
  // OpenMP [2.9.2, Restrictions, C/C++, p.4]
  //   A threadprivate directive for namespace-scope variables must appear
  //   outside any definition or declaration other than the namespace
  //   definition itself.
  if (CanonicalVD->getDeclContext()->isNamespace() &&
      (!getCurLexicalContext()->isFileContext() ||
       !getCurLexicalContext()->Encloses(CanonicalVD->getDeclContext()))) {
    Diag(Id.getLoc(), diag::err_omp_var_scope)
      << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
    bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
                  VarDecl::DeclarationOnly;
    Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
                                     diag::note_defined_here) << VD;
    return ExprError();
  }
  // OpenMP [2.9.2, Restrictions, C/C++, p.6]
  //   A threadprivate directive for static block-scope variables must appear
  //   in the scope of the variable and not in a nested scope.
  if (CanonicalVD->isStaticLocal() && CurScope &&
      !isDeclInScope(ND, getCurLexicalContext(), CurScope)) {
    Diag(Id.getLoc(), diag::err_omp_var_scope)
      << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
    bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
                  VarDecl::DeclarationOnly;
    Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
                                     diag::note_defined_here) << VD;
    return ExprError();
  }

  // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
  //   A threadprivate directive must lexically precede all references to any
  //   of the variables in its list.
  if (VD->isUsed()) {
    Diag(Id.getLoc(), diag::err_omp_var_used)
      << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
    return ExprError();
  }

  QualType ExprType = VD->getType().getNonReferenceType();
  ExprResult DE = BuildDeclRefExpr(VD, ExprType, VK_RValue, Id.getLoc());
  DSAStack->addDSA(VD, cast<DeclRefExpr>(DE.get()), OMPC_threadprivate);
  return DE;
}