Example #1
0
bool ClassTemplateToClass::isValidClassTemplateDecl(ClassTemplateDecl *TmplD)
{
  TemplateParameterList *TPList = TmplD->getTemplateParameters();
  if (TPList->size() != 1)
    return false;

  CXXRecordDecl *CXXRD = TmplD->getTemplatedDecl();
  CXXRecordDecl *Def = CXXRD->getDefinition();
  if (!Def)
    return true;

  NamedDecl *ND = TPList->getParam(0);
  if (dyn_cast<NonTypeTemplateParmDecl>(ND))
    return true;

  if (isUsedNamedDecl(ND, Def))
    return false;

  SmallVector<ClassTemplatePartialSpecializationDecl *, 10> PartialDecls;
  TmplD->getPartialSpecializations(PartialDecls);
  for (SmallVector<ClassTemplatePartialSpecializationDecl *, 10>::iterator 
         I = PartialDecls.begin(), E = PartialDecls.end(); I != E; ++I) {
    if (hasUsedNameDecl(*I))
      return false;
  }

  return true;
}
  ValuePrinterInfo::ValuePrinterInfo(Expr* E, ASTContext* Ctx)
    : m_Expr(E), m_Context(Ctx), m_Flags(0) {
    assert(E && "Expression cannot be null!");
    assert(Ctx && "ASTContext cannot be null!");
    // 1. Get the flags
    const QualType QT = m_Expr->getType();

    if (E->isRValue() || QT.isLocalConstQualified() || QT.isConstant(*Ctx)){
      m_Flags |= VPI_Const;
    }

    if (QT->isPointerType()) {
      // treat arrary-to-pointer decay as array:
      QualType PQT = QT->getPointeeType();
      const Type* PTT = PQT.getTypePtr();
      if (!PTT || !PTT->isArrayType()) {
        m_Flags |= VPI_Ptr;
        if (const RecordType* RT = dyn_cast<RecordType>(QT.getTypePtr()))
          if (RecordDecl* RD = RT->getDecl()) {
            CXXRecordDecl* CRD = dyn_cast<CXXRecordDecl>(RD);
            if (CRD && CRD->isPolymorphic())
              m_Flags |= VPI_Polymorphic;
          }
      }
    }
  }
Example #3
0
/// Warns on methods overridden in DerivedDecl with respect to BaseDecl.
/// FIXME: this warns on all overrides outside of the sliced path in case of
/// multiple inheritance.
void SlicingCheck::DiagnoseSlicedOverriddenMethods(
    const Expr &Call, const CXXRecordDecl &DerivedDecl,
    const CXXRecordDecl &BaseDecl) {
  if (DerivedDecl.getCanonicalDecl() == BaseDecl.getCanonicalDecl())
    return;
  for (const auto &Method : DerivedDecl.methods()) {
    // Virtual destructors are OK. We're ignoring constructors since they are
    // tagged as overrides.
    if (isa<CXXConstructorDecl>(Method) || isa<CXXDestructorDecl>(Method))
      continue;
    if (Method->size_overridden_methods() > 0) {
      diag(Call.getExprLoc(),
           "slicing object from type %0 to %1 discards override %2")
          << &DerivedDecl << &BaseDecl << Method;
    }
  }
  // Recursively process bases.
  for (const auto &Base : DerivedDecl.bases()) {
    if (const auto *BaseRecordType = Base.getType()->getAs<RecordType>()) {
      if (const auto *BaseRecord = cast_or_null<CXXRecordDecl>(
              BaseRecordType->getDecl()->getDefinition()))
        DiagnoseSlicedOverriddenMethods(Call, *BaseRecord, BaseDecl);
    }
  }
}
Example #4
0
   void ValuePrinterInfo::Init(clang::QualType Ty) {
    assert(!Ty.isNull() && "Type must be valid!");
    assert(m_Context && "ASTContext cannot be null!");

    assert(sizeof(m_Type) >= sizeof(clang::QualType) && "m_Type too small!");
    m_Type = *reinterpret_cast<void**>(&Ty);

    // 1. Get the flags
    if (Ty.isLocalConstQualified() || Ty.isConstant(*m_Context)){
      m_Flags |= VPI_Const;
    }

    if (Ty->isPointerType()) {
      // treat arrary-to-pointer decay as array:
      QualType PQT = Ty->getPointeeType();
      const Type* PTT = PQT.getTypePtr();
      if (!PTT || !PTT->isArrayType()) {
        m_Flags |= VPI_Ptr;
        if (const RecordType* RT = dyn_cast<RecordType>(Ty.getTypePtr()))
          if (RecordDecl* RD = RT->getDecl()) {
            CXXRecordDecl* CRD = dyn_cast<CXXRecordDecl>(RD);
            if (CRD && CRD->isPolymorphic())
              m_Flags |= VPI_Polymorphic;
          }
      }
    }
  }
/// \brief Whether this nested name specifier refers to a dependent
/// type or not.
bool NestedNameSpecifier::isDependent() const {
  switch (getKind()) {
  case Identifier:
    // Identifier specifiers always represent dependent types
    return true;

  case Namespace:
  case NamespaceAlias:
  case Global:
    return false;

  case Super: {
    CXXRecordDecl *RD = static_cast<CXXRecordDecl *>(Specifier);
    for (const auto &Base : RD->bases())
      if (Base.getType()->isDependentType())
        return true;

    return false;
  }

  case TypeSpec:
  case TypeSpecWithTemplate:
    return getAsType()->isDependentType();
  }

  llvm_unreachable("Invalid NNS Kind!");
}
Example #6
0
bool Sema::ActOnSuperScopeSpecifier(SourceLocation SuperLoc,
                                    SourceLocation ColonColonLoc,
                                    CXXScopeSpec &SS) {
  CXXRecordDecl *RD = nullptr;
  for (Scope *S = getCurScope(); S; S = S->getParent()) {
    if (S->isFunctionScope()) {
      if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(S->getEntity()))
        RD = MD->getParent();
      break;
    }
    if (S->isClassScope()) {
      RD = cast<CXXRecordDecl>(S->getEntity());
      break;
    }
  }

  if (!RD) {
    Diag(SuperLoc, diag::err_invalid_super_scope);
    return true;
  } else if (RD->isLambda()) {
    Diag(SuperLoc, diag::err_super_in_lambda_unsupported);
    return true;
  } else if (RD->getNumBases() == 0) {
    Diag(SuperLoc, diag::err_no_base_classes) << RD->getName();
    return true;
  }

  SS.MakeSuper(Context, RD, SuperLoc, ColonColonLoc);
  return false;
}
void RecordInfo::walkBases() {
  // This traversal is akin to CXXRecordDecl::forallBases()'s,
  // but without stepping over dependent bases -- these might also
  // have a "GC base name", so are to be included and considered.
  SmallVector<const CXXRecordDecl*, 8> queue;

  const CXXRecordDecl *base_record = record();
  while (true) {
    for (const auto& it : base_record->bases()) {
      const RecordType *type = it.getType()->getAs<RecordType>();
      CXXRecordDecl* base;
      if (!type)
        base = GetDependentTemplatedDecl(*it.getType());
      else {
        base = cast_or_null<CXXRecordDecl>(type->getDecl()->getDefinition());
        if (base)
          queue.push_back(base);
      }
      if (!base)
        continue;

      const std::string& name = base->getName();
      if (Config::IsGCBase(name)) {
        gc_base_names_.push_back(name);
        is_gc_derived_ = true;
      }
    }

    if (queue.empty())
      break;
    base_record = queue.pop_back_val(); // not actually a queue.
  }
}
Example #8
0
   /**
    * Return the concrete type in the same extensible class string as me, or
    * NULL if it can't be found.
    *
    * This query only really makes sense for an extensible class.
    */
   CXXRecordDecl* getAssociatedConcreteType(CXXRecordDecl* decl) {

      // a concrete type is always part of its own extensible class string.
      if (isOMRConcreteType(decl))
         return decl;

      // Only extensible decls have a meaningful concrete class string.
      if (isExtensible(decl)) {
         int loopCount = 0;
         CXXRecordDecl* concrete = mostDerivedType(decl);
         trace("==isExtensible: " << decl->getQualifiedNameAsString() << " concrete: " << (concrete ? concrete->getQualifiedNameAsString() : "no concrete found"));
         while (concrete) {
            if (loopCount++ > 50) {
               std::string diagnostic("Found more than 50 layers of classes, likely bug.");
               DiagnosticsEngine &diagEngine = Context->getDiagnostics();
               unsigned diagID = diagEngine.getCustomDiagID(DiagnosticsEngine::Error, "%0");
               diagEngine.Report(decl->getLocation(), diagID) << diagnostic;
               exit(EXIT_FAILURE);
            }
            if (inSameClassString(decl, concrete)) {
               trace("=== in same string");
               return concrete;  //Found the concrete class in the same string.
            }

            concrete = mostDerivedType(concrete);
            if (concrete) trace("==== new concrete  " << concrete->getQualifiedNameAsString() << " for " << decl->getQualifiedNameAsString());
         }

         trace("Didn't find a concrete class for " << decl->getQualifiedNameAsString() << " ... issue diagnostic?")
      }
      return NULL;
   }
void ReduceClassTemplateParameter::removeParameterFromMethods()
{
  CXXRecordDecl *CXXRD = TheClassTemplateDecl->getTemplatedDecl();
  for (auto I = CXXRD->method_begin(), E = CXXRD->method_end();
       I != E; ++I) {
    ClassTemplateMethodVisitor V(this, TheParameterIndex);
    V.TraverseDecl(*I);
  }
}
void ASTConsumerHTML::HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) {
    CXXRecordDecl *decl = RD;
    if (decl) {
        log << "\n" << static_cast<Decl *> (decl) << " HandleVTable" << "\n";
        decl->print(log);
        log << "\n";
    }

}
Example #11
0
void QGetEnv::VisitStmt(clang::Stmt *stmt)
{
    // Lets check only in function calls. Otherwise there are too many false positives, it's common
    // to implicit cast to bool when checking pointers for validity, like if (ptr)

    CXXMemberCallExpr *memberCall = dyn_cast<CXXMemberCallExpr>(stmt);
    if (!memberCall)
        return;

    CXXMethodDecl *method = memberCall->getMethodDecl();
    if (!method)
        return;

    CXXRecordDecl *record = method->getParent();
    if (!record || record->getNameAsString() != "QByteArray") {
        return;
    }

    std::vector<CallExpr *> calls = Utils::callListForChain(memberCall);
    if (calls.size() != 2)
        return;

    CallExpr *qgetEnvCall = calls.back();

    FunctionDecl *func = qgetEnvCall->getDirectCallee();

    if (!func || func->getNameAsString() != "qgetenv")
        return;

    string methodname = method->getNameAsString();
    string errorMsg;
    std::string replacement;
    if (methodname == "isEmpty") {
        errorMsg = "qgetenv().isEmpty() allocates.";
        replacement = "qEnvironmentVariableIsEmpty";
    } else if (methodname == "isNull") {
        errorMsg = "qgetenv().isNull() allocates.";
        replacement = "qEnvironmentVariableIsSet";
    } else if (methodname == "toInt") {
        errorMsg = "qgetenv().toInt() is slow.";
        replacement = "qEnvironmentVariableIntValue";
    }

    if (!errorMsg.empty()) {
        std::vector<FixItHint> fixits;
        if (isFixitEnabled(FixitAll)) {
            const bool success = FixItUtils::transformTwoCallsIntoOne(m_ci, qgetEnvCall, memberCall, replacement, fixits);
            if (!success) {
                queueManualFixitWarning(memberCall->getLocStart(), FixitAll);
            }
        }

        errorMsg += " Use " + replacement + "() instead";
        emitWarning(memberCall->getLocStart(), errorMsg.c_str(), fixits);
    }
}
bool
UnnecessaryIncludeFinder::VisitTemplateSpecializationTypeLoc (
    TemplateSpecializationTypeLoc typeLoc)
{
  CXXRecordDecl* pCXXRecordDecl = typeLoc.getTypePtr()->getAsCXXRecordDecl();
  if (pCXXRecordDecl) {
    markUsed(pCXXRecordDecl->getLocation(), typeLoc.getTemplateNameLoc());
  }
  return true;
}
Example #13
0
bool CXXRecordDecl::lookupInBases(BaseMatchesCallback BaseMatches,
                                  CXXBasePaths &Paths,
                                  bool LookupInDependent) const {
  // If we didn't find anything, report that.
  if (!Paths.lookupInBases(getASTContext(), this, BaseMatches,
                           LookupInDependent))
    return false;

  // If we're not recording paths or we won't ever find ambiguities,
  // we're done.
  if (!Paths.isRecordingPaths() || !Paths.isFindingAmbiguities())
    return true;
  
  // C++ [class.member.lookup]p6:
  //   When virtual base classes are used, a hidden declaration can be
  //   reached along a path through the sub-object lattice that does
  //   not pass through the hiding declaration. This is not an
  //   ambiguity. The identical use with nonvirtual base classes is an
  //   ambiguity; in that case there is no unique instance of the name
  //   that hides all the others.
  //
  // FIXME: This is an O(N^2) algorithm, but DPG doesn't see an easy
  // way to make it any faster.
  Paths.Paths.remove_if([&Paths](const CXXBasePath &Path) {
    for (const CXXBasePathElement &PE : Path) {
      if (!PE.Base->isVirtual())
        continue;

      CXXRecordDecl *VBase = nullptr;
      if (const RecordType *Record = PE.Base->getType()->getAs<RecordType>())
        VBase = cast<CXXRecordDecl>(Record->getDecl());
      if (!VBase)
        break;

      // The declaration(s) we found along this path were found in a
      // subobject of a virtual base. Check whether this virtual
      // base is a subobject of any other path; if so, then the
      // declaration in this path are hidden by that patch.
      for (const CXXBasePath &HidingP : Paths) {
        CXXRecordDecl *HidingClass = nullptr;
        if (const RecordType *Record =
                HidingP.back().Base->getType()->getAs<RecordType>())
          HidingClass = cast<CXXRecordDecl>(Record->getDecl());
        if (!HidingClass)
          break;

        if (HidingClass->isVirtuallyDerivedFrom(VBase))
          return true;
      }
    }
    return false;
  });

  return true;
}
Example #14
0
static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D,
                         llvm::Constant *DeclPtr) {
  assert(D.hasGlobalStorage() && "VarDecl must have global storage!");
  assert(!D.getType()->isReferenceType() && 
         "Should not call EmitDeclInit on a reference!");
  
  CodeGenModule &CGM = CGF.CGM;
  ASTContext &Context = CGF.getContext();
    
  const Expr *Init = D.getInit();
  QualType T = D.getType();
  bool isVolatile = Context.getCanonicalType(T).isVolatileQualified();

  if (!CGF.hasAggregateLLVMType(T)) {
    llvm::Value *V = CGF.EmitScalarExpr(Init);
    CGF.EmitStoreOfScalar(V, DeclPtr, isVolatile, T);
  } else if (T->isAnyComplexType()) {
    CGF.EmitComplexExprIntoAddr(Init, DeclPtr, isVolatile);
  } else {
    CGF.EmitAggExpr(Init, DeclPtr, isVolatile);
    
    // Avoid generating destructor(s) for initialized objects. 
    if (!isa<CXXConstructExpr>(Init))
      return;
    
    const ConstantArrayType *Array = Context.getAsConstantArrayType(T);
    if (Array)
      T = Context.getBaseElementType(Array);
    
    const RecordType *RT = T->getAs<RecordType>();
    if (!RT)
      return;
    
    CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
    if (RD->hasTrivialDestructor())
      return;
    
    CXXDestructorDecl *Dtor = RD->getDestructor(Context);
    
    llvm::Constant *DtorFn;
    if (Array) {
      DtorFn = 
        CodeGenFunction(CGM).GenerateCXXAggrDestructorHelper(Dtor, 
                                                             Array, 
                                                             DeclPtr);
      const llvm::Type *Int8PtrTy =
        llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
      DeclPtr = llvm::Constant::getNullValue(Int8PtrTy);
     } else
      DtorFn = CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete);

    CGF.EmitCXXGlobalDtorRegistration(DtorFn, DeclPtr);
  }
}
static bool isParentOf(const CXXRecordDecl &Parent,
                       const CXXRecordDecl &ThisClass) {
  if (Parent.getCanonicalDecl() == ThisClass.getCanonicalDecl())
    return true;
  const CXXRecordDecl *ParentCanonicalDecl = Parent.getCanonicalDecl();
  return ThisClass.bases_end() !=
         llvm::find_if(ThisClass.bases(), [=](const CXXBaseSpecifier &Base) {
           auto *BaseDecl = Base.getType()->getAsCXXRecordDecl();
           assert(BaseDecl);
           return ParentCanonicalDecl == BaseDecl->getCanonicalDecl();
         });
}
Example #16
0
   /**
    * Once the recursive visitor has completed, this routine analyzes the
    * MostDerivedTypeMap to find errors in the structure of the OMR classes
    */
   void VerifyTypeStructure() {
      trace("Starting Structure Verification");

      for (std::map<CXXRecordDecl*, bool>::iterator I = Types.begin(), E=Types.end(); I != E; ++I) {
         CXXRecordDecl * Type        = I->first;
         bool extensible             = I->second;
         trace(Type << " " << extensible << " " << getAssociatedConcreteType(Type));
         if (extensible && !getAssociatedConcreteType(Type)) {
            trace("xxxx Issue diagnostic because there's no associated concrete type");
            continue;
         }
         if (extensible) {  //Extnsible type .
            trace("xxxx Verifying " << Type->getQualifiedNameAsString() << " has no non-extensible base classes." );
            for (CXXRecordDecl::base_class_iterator BI = Type->bases_begin(), BE = Type->bases_end(); BI != BE; ++BI) {
               CXXRecordDecl * base_class = BI->getType()->getAsCXXRecordDecl();
               if (base_class
                   && !isExtensible(base_class) // Ensure extensible parent.
                   && !isOMRRootType(Type)) {   // OMR Root type can have non-extensible parents.
                  //Base is not extensible, but an extensible type reaches it, with no concrete class in the middle.
                  //Issue diagnostic.
                  std::string diagnostic("OMR_EXTENSIBLE Type ");
                  diagnostic += Type->getQualifiedNameAsString();
                  diagnostic += " derives from ";
                  diagnostic += base_class->getQualifiedNameAsString();
                  diagnostic += " that is not marked as OMR_EXTENSIBLE.\n";

                  DiagnosticsEngine &diagEngine = Context->getDiagnostics();
                  unsigned diagID = diagEngine.getCustomDiagID(DiagnosticsEngine::Error, "%0");
                  diagEngine.Report(base_class->getLocation(), diagID) << diagnostic;
               }
            }
         } else {
            trace("xxxx Verifying " << Type->getQualifiedNameAsString() << " has no non-extensible base classes." );
            for (CXXRecordDecl::base_class_iterator BI = Type->bases_begin(), BE = Type->bases_end(); BI != BE; ++BI) {
               CXXRecordDecl * base_class = BI->getType()->getAsCXXRecordDecl();
               if (base_class && isExtensible(base_class) && !isOMRConcreteType(base_class)) {
                  //Base is not extensible, but an extensible type reaches it, with no concrete class in the middle.
                  //Issue diagnostic.
                  std::string diagnostic("Type ");
                  diagnostic += Type->getQualifiedNameAsString();
                  diagnostic += " derives from ";
                  diagnostic += base_class->getQualifiedNameAsString();
                  diagnostic += " that is  marked as OMR_EXTENSIBLE.\n";

                  DiagnosticsEngine &diagEngine = Context->getDiagnostics();
                  unsigned diagID = diagEngine.getCustomDiagID(DiagnosticsEngine::Error, "%0");
                  diagEngine.Report(Type->getLocation(), diagID) << diagnostic;
               }
            }
         }
      } //each most derived type
   }
Example #17
0
// A GC mixin is a class that inherits from a GC mixin base and has
// has not yet been "mixed in" with another GC base class.
bool RecordInfo::IsGCMixin() {
  if (!IsGCDerived() || base_paths_->begin() == base_paths_->end())
    return false;
  // Get the last element of the first path.
  CXXBasePaths::paths_iterator it = base_paths_->begin();
  const CXXBasePathElement& elem = (*it)[it->size() - 1];
  CXXRecordDecl* base = elem.Base->getType()->getAsCXXRecordDecl();
  // If it is not a mixin base we are done.
  if (!Config::IsGCMixinBase(base->getName()))
    return false;
  // This is a mixin if there are no other paths to GC bases.
  return ++it == base_paths_->end();
}
Example #18
0
bool RecordInfo::IsGCFinalized() {
  if (!IsGCDerived())
    return false;
  for (CXXBasePaths::paths_iterator it = base_paths_->begin();
       it != base_paths_->end();
       ++it) {
    const CXXBasePathElement& elem = (*it)[it->size() - 1];
    CXXRecordDecl* base = elem.Base->getType()->getAsCXXRecordDecl();
    if (Config::IsGCFinalizedBase(base->getName()))
      return true;
  }
  return false;
}
Example #19
0
static CXXRecordDecl *FindDeclaringClass(NamedDecl *D) {
  DeclContext *DC = D->getDeclContext();

  // This can only happen at top: enum decls only "publish" their
  // immediate members.
  if (isa<EnumDecl>(DC))
    DC = cast<EnumDecl>(DC)->getDeclContext();

  CXXRecordDecl *DeclaringClass = cast<CXXRecordDecl>(DC);
  while (DeclaringClass->isAnonymousStructOrUnion())
    DeclaringClass = cast<CXXRecordDecl>(DeclaringClass->getDeclContext());
  return DeclaringClass;
}
Example #20
0
void RuleOfTwoSoft::VisitStmt(Stmt *s)
{
    CXXOperatorCallExpr *op = dyn_cast<CXXOperatorCallExpr>(s);
    if (op) {
        FunctionDecl *func = op->getDirectCallee();
        if (func && func->getNameAsString() == "operator=") {
            CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(func);
            if (method && method->getParent()) {
                CXXRecordDecl *record = method->getParent();
                const bool hasCopyCtor = record->hasNonTrivialCopyConstructor();
                const bool hasCopyAssignOp = record->hasNonTrivialCopyAssignment();
                if (hasCopyCtor && !hasCopyAssignOp && !isBlacklisted(record)) {
                    string msg = "Using assign operator but class " + record->getQualifiedNameAsString() + " has copy-ctor but no assign operator";
                    emitWarning(s->getLocStart(), msg);
                }
            }
        }
    } else if (CXXConstructExpr *ctorExpr = dyn_cast<CXXConstructExpr>(s)) {
        CXXConstructorDecl *ctorDecl = ctorExpr->getConstructor();
        CXXRecordDecl *record = ctorDecl->getParent();
        if (ctorDecl->isCopyConstructor() && record) {
            const bool hasCopyCtor = record->hasNonTrivialCopyConstructor();
            const bool hasCopyAssignOp = record->hasNonTrivialCopyAssignment();
            if (!hasCopyCtor && hasCopyAssignOp && !isBlacklisted(record)) {
                string msg = "Using copy-ctor but class " + record->getQualifiedNameAsString() + " has a trivial copy-ctor but non trivial assign operator";
                emitWarning(s->getLocStart(), msg);
            }
        }
    }
}
Example #21
0
/// Determines whether the given friend class template matches
/// anything in the effective context.
static AccessResult MatchesFriend(Sema &S,
                                  const EffectiveContext &EC,
                                  ClassTemplateDecl *Friend) {
  AccessResult OnFailure = AR_inaccessible;

  // Check whether the friend is the template of a class in the
  // context chain.
  for (llvm::SmallVectorImpl<CXXRecordDecl*>::const_iterator
         I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
    CXXRecordDecl *Record = *I;

    // Figure out whether the current class has a template:
    ClassTemplateDecl *CTD;

    // A specialization of the template...
    if (isa<ClassTemplateSpecializationDecl>(Record)) {
      CTD = cast<ClassTemplateSpecializationDecl>(Record)
        ->getSpecializedTemplate();

    // ... or the template pattern itself.
    } else {
      CTD = Record->getDescribedClassTemplate();
      if (!CTD) continue;
    }

    // It's a match.
    if (Friend == CTD->getCanonicalDecl())
      return AR_accessible;

    // If the context isn't dependent, it can't be a dependent match.
    if (!EC.isDependent())
      continue;

    // If the template names don't match, it can't be a dependent
    // match.  This isn't true in C++0x because of template aliases.
    if (!S.LangOpts.CPlusPlus0x && CTD->getDeclName() != Friend->getDeclName())
      continue;

    // If the class's context can't instantiate to the friend's
    // context, it can't be a dependent match.
    if (!MightInstantiateTo(S, CTD->getDeclContext(),
                            Friend->getDeclContext()))
      continue;

    // Otherwise, it's a dependent match.
    OnFailure = AR_dependent;
  }

  return OnFailure;
}
TEST_F(StructuralEquivalenceTest, WrongOrderOfFieldsInClass) {
  auto Code = "class X { int a; int b; };";
  auto Decls = makeNamedDecls(Code, Code, Lang_CXX, "X");

  CXXRecordDecl *RD = FirstDeclMatcher<CXXRecordDecl>().match(
      get<1>(Decls), cxxRecordDecl(hasName("X")));
  FieldDecl *FD =
      FirstDeclMatcher<FieldDecl>().match(get<1>(Decls), fieldDecl(hasName("a")));

  // Reorder the FieldDecls
  RD->removeDecl(FD);
  RD->addDeclInternal(FD);

  EXPECT_FALSE(testStructuralMatch(Decls));
}
Example #23
0
void FunctionArgsByRef::VisitDecl(Decl *decl)
{
    FunctionDecl *functionDecl = dyn_cast<FunctionDecl>(decl);
    if (functionDecl == nullptr || !functionDecl->hasBody() || shouldIgnoreFunction(functionDecl->getNameAsString())
            || !functionDecl->isThisDeclarationADefinition()) return;

    Stmt *body = functionDecl->getBody();

    for (auto it = functionDecl->param_begin(), end = functionDecl->param_end(); it != end; ++it) {
        const ParmVarDecl *param = *it;
        QualType paramQt = param->getType();
        const Type *paramType = paramQt.getTypePtrOrNull();
        if (paramType == nullptr || paramType->isDependentType())
            continue;

        const int size_of_T = m_ci.getASTContext().getTypeSize(paramQt) / 8;
        const bool isSmall = size_of_T <= 16; // TODO: What about arm ?
        CXXRecordDecl *recordDecl = paramType->getAsCXXRecordDecl();
        const bool isUserNonTrivial = recordDecl && (recordDecl->hasUserDeclaredCopyConstructor() || recordDecl->hasUserDeclaredDestructor());
        const bool isReference = paramType->isLValueReferenceType();
        const bool isConst = paramQt.isConstQualified();
        if (recordDecl && shouldIgnoreClass(recordDecl->getQualifiedNameAsString()))
            continue;

        std::string error;
        if (isConst && !isReference) {
            if (!isSmall) {
                error += warningMsgForSmallType(size_of_T, paramQt.getAsString());
            } else if (isUserNonTrivial) {
                error += "Missing reference on non-trivial type " + recordDecl->getQualifiedNameAsString();
            }
        } else if (isConst && isReference && !isUserNonTrivial && isSmall) {
            //error += "Don't use by-ref on small trivial type";
        } else if (!isConst && !isReference && (!isSmall || isUserNonTrivial)) {
            if (Utils::containsNonConstMemberCall(body, param) || Utils::containsCallByRef(body, param))
                continue;
            if (!isSmall) {
                error += warningMsgForSmallType(size_of_T, paramQt.getAsString());
            } else if (isUserNonTrivial) {
                error += "Missing reference on non-trivial type " + recordDecl->getQualifiedNameAsString();
            }
        }

        if (!error.empty()) {
            emitWarning(param->getLocStart(), error.c_str());
        }
    }
}
Example #24
0
void MissingTypeinfo::registerQTypeInfo(ClassTemplateSpecializationDecl *decl)
{
    if (decl->getName() == "QTypeInfo") {
        auto &args = decl->getTemplateArgs();
        if (args.size() != 1)
            return;

        QualType qt = args[0].getAsType();
        const Type *t = qt.getTypePtrOrNull();
        CXXRecordDecl *recordDecl =  t ? t->getAsCXXRecordDecl() : nullptr;
        // llvm::errs() << qt.getAsString() << " foo\n";
        if (recordDecl != nullptr) {
            m_typeInfos.insert(recordDecl->getQualifiedNameAsString());
        }
    }
}
Example #25
0
void VarCheckVisitor::checkClass(clang::Decl* d)
{
  auto loc = getDeclLocation(d);

  CXXRecordDecl* c = (CXXRecordDecl*)d;

  string name = c->getName();

  boost::regex r{CLASS_NAME};

  if(!boost::regex_match(name, r)){
    lineIssues_.push_back(Issue(loc.first, loc.second,
    "Incorrect Class/Struct name",
    "Classes and Structures should be named in upper camel case.",
    WARNING));
  }
}
Example #26
0
bool RecordInfo::IsTreeShared() {
  if (Config::IsTreeSharedBase(name_))
    return true;
  if (!IsGCDerived())
    return false;
  for (CXXBasePaths::paths_iterator it = base_paths_->begin();
       it != base_paths_->end();
       ++it) {
    // TreeShared is an immediate base of GCFinalized.
    if (it->size() < 2) continue;
    const CXXBasePathElement& elem = (*it)[it->size() - 2];
    CXXRecordDecl* base = elem.Base->getType()->getAsCXXRecordDecl();
    if (Config::IsTreeSharedBase(base->getName()))
      return true;
  }
  return false;
}
void MustOverrideChecker::check(const MatchFinder::MatchResult &Result) {
  auto D = Result.Nodes.getNodeAs<CXXRecordDecl>("class");

  // Look through all of our immediate bases to find methods that need to be
  // overridden
  typedef std::vector<CXXMethodDecl *> OverridesVector;
  OverridesVector MustOverrides;
  for (const auto &Base : D->bases()) {
    // The base is either a class (CXXRecordDecl) or it's a templated class...
    CXXRecordDecl *Parent = Base.getType()
                                .getDesugaredType(D->getASTContext())
                                ->getAsCXXRecordDecl();
    // The parent might not be resolved to a type yet. In this case, we can't
    // do any checking here. For complete correctness, we should visit
    // template instantiations, but this case is likely to be rare, so we will
    // ignore it until it becomes important.
    if (!Parent) {
      continue;
    }
    Parent = Parent->getDefinition();
    for (const auto &M : Parent->methods()) {
      if (hasCustomAnnotation(M, "moz_must_override"))
        MustOverrides.push_back(M);
    }
  }

  for (auto &O : MustOverrides) {
    bool Overridden = false;
    for (const auto &M : D->methods()) {
      // The way that Clang checks if a method M overrides its parent method
      // is if the method has the same name but would not overload.
      if (getNameChecked(M) == getNameChecked(O) &&
          !CI->getSema().IsOverload(M, O, false)) {
        Overridden = true;
        break;
      }
    }
    if (!Overridden) {
      diag(D->getLocation(), "%0 must override %1", DiagnosticIDs::Error)
          << D->getDeclName() << O->getDeclName();
      diag(O->getLocation(), "function to override is here",
           DiagnosticIDs::Note);
    }
  }
}
Example #28
0
/// Find the current instantiation that associated with the given type.
static CXXRecordDecl *getCurrentInstantiationOf(QualType T,
                                                DeclContext *CurContext) {
  if (T.isNull())
    return nullptr;

  const Type *Ty = T->getCanonicalTypeInternal().getTypePtr();
  if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
    CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordTy->getDecl());
    if (!Record->isDependentContext() ||
        Record->isCurrentInstantiation(CurContext))
      return Record;

    return nullptr;
  } else if (isa<InjectedClassNameType>(Ty))
    return cast<InjectedClassNameType>(Ty)->getDecl();
  else
    return nullptr;
}
Example #29
0
File: Utils.cpp Project: KDE/clazy
bool Utils::hasMember(CXXRecordDecl *record, const string &memberTypeName)
{
    if (!record)
        return false;

    for (auto field : record->fields()) {
        field->getParent()->getNameAsString();
        QualType qt = field->getType();
        const Type *t = qt.getTypePtrOrNull();
        if (t && t->getAsCXXRecordDecl()) {
            CXXRecordDecl *rec = t->getAsCXXRecordDecl();
            if (rec->getNameAsString() == memberTypeName)
                return true;
        }
    }

    return false;
}
void CopyablePolymorphic::VisitDecl(clang::Decl *decl)
{
    CXXRecordDecl *record = dyn_cast<CXXRecordDecl>(decl);
    if (!record || !record->hasDefinition() || record->getDefinition() != record || !record->isPolymorphic())
        return;

    CXXConstructorDecl *copyCtor = Utils::copyCtor(record);
    CXXMethodDecl *copyAssign = Utils::copyAssign(record);

    const bool hasCallableCopyCtor = copyCtor && !copyCtor->isDeleted() && copyCtor->getAccess() != clang::AS_private;
    const bool hasCallableCopyAssign = copyAssign && !copyAssign->isDeleted() && copyAssign->getAccess() != clang::AS_private;

    if (!hasCallableCopyCtor && !hasCallableCopyAssign)
        return;


    emitWarning(record->getLocStart(), "Polymorphic class is copyable. Potential slicing.");
}