CXXConstructorDecl *CXXRecordDecl::getCopyConstructor(ASTContext &Context, unsigned TypeQuals) const{ QualType ClassType = Context.getTypeDeclType(const_cast<CXXRecordDecl*>(this)); DeclarationName ConstructorName = Context.DeclarationNames.getCXXConstructorName( Context.getCanonicalType(ClassType)); unsigned FoundTQs; llvm::SmallVector<std::pair<CXXMethodDecl *, Qualifiers>, 4> Found; DeclContext::lookup_const_iterator Con, ConEnd; for (llvm::tie(Con, ConEnd) = this->lookup(ConstructorName); Con != ConEnd; ++Con) { // C++ [class.copy]p2: // A non-template constructor for class X is a copy constructor if [...] if (isa<FunctionTemplateDecl>(*Con)) continue; CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con); if (Constructor->isCopyConstructor(FoundTQs)) { if (((TypeQuals & Qualifiers::Const) == (FoundTQs & Qualifiers::Const)) || (!(TypeQuals & Qualifiers::Const) && (FoundTQs & Qualifiers::Const))) Found.push_back(std::make_pair( const_cast<CXXConstructorDecl *>(Constructor), Qualifiers::fromCVRMask(FoundTQs))); } } return cast_or_null<CXXConstructorDecl>( GetBestOverloadCandidateSimple(Found)); }
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); } } } }