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. } }
// 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(); }
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; }
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)); } }
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; }