/// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function. /// "TheDeclarator" is the declarator that this will be added to. DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic, SourceLocation EllipsisLoc, ParamInfo *ArgInfo, unsigned NumArgs, unsigned TypeQuals, bool hasExceptionSpec, SourceLocation ThrowLoc, bool hasAnyExceptionSpec, ActionBase::TypeTy **Exceptions, SourceRange *ExceptionRanges, unsigned NumExceptions, SourceLocation LPLoc, SourceLocation RPLoc, Declarator &TheDeclarator) { DeclaratorChunk I; I.Kind = Function; I.Loc = LPLoc; I.EndLoc = RPLoc; I.Fun.hasPrototype = hasProto; I.Fun.isVariadic = isVariadic; I.Fun.EllipsisLoc = EllipsisLoc.getRawEncoding(); I.Fun.DeleteArgInfo = false; I.Fun.TypeQuals = TypeQuals; I.Fun.NumArgs = NumArgs; I.Fun.ArgInfo = 0; I.Fun.hasExceptionSpec = hasExceptionSpec; I.Fun.ThrowLoc = ThrowLoc.getRawEncoding(); I.Fun.hasAnyExceptionSpec = hasAnyExceptionSpec; I.Fun.NumExceptions = NumExceptions; I.Fun.Exceptions = 0; // new[] an argument array if needed. if (NumArgs) { // If the 'InlineParams' in Declarator is unused and big enough, put our // parameter list there (in an effort to avoid new/delete traffic). If it // is already used (consider a function returning a function pointer) or too // small (function taking too many arguments), go to the heap. if (!TheDeclarator.InlineParamsUsed && NumArgs <= llvm::array_lengthof(TheDeclarator.InlineParams)) { I.Fun.ArgInfo = TheDeclarator.InlineParams; I.Fun.DeleteArgInfo = false; TheDeclarator.InlineParamsUsed = true; } else { I.Fun.ArgInfo = new DeclaratorChunk::ParamInfo[NumArgs]; I.Fun.DeleteArgInfo = true; } memcpy(I.Fun.ArgInfo, ArgInfo, sizeof(ArgInfo[0])*NumArgs); } // new[] an exception array if needed if (NumExceptions) { I.Fun.Exceptions = new DeclaratorChunk::TypeAndRange[NumExceptions]; for (unsigned i = 0; i != NumExceptions; ++i) { I.Fun.Exceptions[i].Ty = Exceptions[i]; I.Fun.Exceptions[i].Range = ExceptionRanges[i]; } } return I; }
static void checkAllProps(MigrationContext &MigrateCtx, std::vector<ObjCPropertyDecl *> &AllProps) { typedef llvm::TinyPtrVector<ObjCPropertyDecl *> IndivPropsTy; llvm::DenseMap<unsigned, IndivPropsTy> AtProps; for (unsigned i = 0, e = AllProps.size(); i != e; ++i) { ObjCPropertyDecl *PD = AllProps[i]; if (PD->getPropertyAttributesAsWritten() & (ObjCPropertyDecl::OBJC_PR_assign | ObjCPropertyDecl::OBJC_PR_readonly)) { SourceLocation AtLoc = PD->getAtLoc(); if (AtLoc.isInvalid()) continue; unsigned RawAt = AtLoc.getRawEncoding(); AtProps[RawAt].push_back(PD); } } for (llvm::DenseMap<unsigned, IndivPropsTy>::iterator I = AtProps.begin(), E = AtProps.end(); I != E; ++I) { SourceLocation AtLoc = SourceLocation::getFromRawEncoding(I->first); IndivPropsTy &IndProps = I->second; checkAllAtProps(MigrateCtx, AtLoc, IndProps); } }
CXSourceLocation lfort_getLocation(CXProgram tu, CXFile file, unsigned line, unsigned column) { if (!tu || !file) return lfort_getNullLocation(); bool Logging = ::getenv("LIBLFORT_LOGGING"); ASTUnit *CXXUnit = static_cast<ASTUnit *>(tu->PgmData); ASTUnit::ConcurrencyCheck Check(*CXXUnit); const FileEntry *File = static_cast<const FileEntry *>(file); SourceLocation SLoc = CXXUnit->getLocation(File, line, column); if (SLoc.isInvalid()) { if (Logging) llvm::errs() << "lfort_getLocation(\"" << File->getName() << "\", " << line << ", " << column << ") = invalid\n"; return lfort_getNullLocation(); } if (Logging) llvm::errs() << "lfort_getLocation(\"" << File->getName() << "\", " << line << ", " << column << ") = " << SLoc.getRawEncoding() << "\n"; return cxloc::translateSourceLocation(CXXUnit->getASTContext(), SLoc); }
bool EditedSource::commitInsert(SourceLocation OrigLoc, FileOffset Offs, StringRef text, bool beforePreviousInsertions) { if (!canInsertInOffset(OrigLoc, Offs)) return false; if (text.empty()) return true; if (SourceMgr.isMacroArgExpansion(OrigLoc)) { SourceLocation DefArgLoc = SourceMgr.getImmediateExpansionRange(OrigLoc).first; SourceLocation ExpLoc = SourceMgr.getImmediateExpansionRange(DefArgLoc).first; ExpansionToArgMap[ExpLoc.getRawEncoding()] = DefArgLoc; } FileEdit &FA = FileEdits[Offs]; if (FA.Text.empty()) { FA.Text = copyString(text); return true; } if (beforePreviousInsertions) FA.Text = copyString(Twine(text) + FA.Text); else FA.Text = copyString(Twine(FA.Text) + text); return true; }
CXCursor cxcursor::MakeCursorTypeRef(TypeDecl *Type, SourceLocation Loc, ASTUnit *TU) { assert(Type && TU && "Invalid arguments!"); void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding()); CXCursor C = { CXCursor_TypeRef, { Type, RawLoc, TU } }; return C; }
bool EditedSource::canInsertInOffset(SourceLocation OrigLoc, FileOffset Offs) { FileEditsTy::iterator FA = getActionForOffset(Offs); if (FA != FileEdits.end()) { if (FA->first != Offs) return false; // position has been removed. } if (SourceMgr.isMacroArgExpansion(OrigLoc)) { IdentifierInfo *II; SourceLocation ExpLoc; deconstructMacroArgLoc(OrigLoc, ExpLoc, II); auto I = ExpansionToArgMap.find(ExpLoc.getRawEncoding()); if (I != ExpansionToArgMap.end() && std::find(I->second.begin(), I->second.end(), II) != I->second.end()) { // Trying to write in a macro argument input that has already been // written by a previous commit for another expansion of the same macro // argument name. For example: // // \code // #define MAC(x) ((x)+(x)) // MAC(a) // \endcode // // A commit modified the macro argument 'a' due to the first '(x)' // expansion inside the macro definition, and a subsequent commit tried // to modify 'a' again for the second '(x)' expansion. The edits of the // second commit will be rejected. return false; } } return true; }
/// Save a source location to the given buffer. static void SaveSourceLocation(SourceLocation Loc, char *&Buffer, unsigned &BufferSize, unsigned &BufferCapacity) { unsigned Raw = Loc.getRawEncoding(); Append(reinterpret_cast<char *>(&Raw), reinterpret_cast<char *>(&Raw) + sizeof(unsigned), Buffer, BufferSize, BufferCapacity); }
CXCursor cxcursor::MakeCursorObjCSuperClassRef(ObjCInterfaceDecl *Super, SourceLocation Loc, CXTranslationUnit TU) { assert(Super && TU && "Invalid arguments!"); void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding()); CXCursor C = { CXCursor_ObjCSuperClassRef, { Super, RawLoc, TU } }; return C; }
CXCursor cxcursor::MakeCursorObjCProtocolRef(const ObjCProtocolDecl *Proto, SourceLocation Loc, CXTranslationUnit TU) { assert(Proto && TU && "Invalid arguments!"); void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding()); CXCursor C = { CXCursor_ObjCProtocolRef, 0, { (void*)Proto, RawLoc, TU } }; return C; }
CXCursor cxcursor::MakeCursorLabelRef(LabelStmt *Label, SourceLocation Loc, CXTranslationUnit TU) { assert(Label && TU && "Invalid arguments!"); void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding()); CXCursor C = { CXCursor_LabelRef, { Label, RawLoc, TU } }; return C; }
CXCursor cxcursor::MakeCursorTemplateRef(TemplateDecl *Template, SourceLocation Loc, CXTranslationUnit TU) { assert(Template && TU && "Invalid arguments!"); void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding()); CXCursor C = { CXCursor_TemplateRef, { Template, RawLoc, TU } }; return C; }
CXCursor cxcursor::MakeCursorObjCProtocolRef(ObjCProtocolDecl *Super, SourceLocation Loc, ASTUnit *TU) { assert(Super && TU && "Invalid arguments!"); void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding()); CXCursor C = { CXCursor_ObjCProtocolRef, { Super, RawLoc, TU } }; return C; }
CXCursor cxcursor::MakeCursorObjCClassRef(ObjCInterfaceDecl *Class, SourceLocation Loc, ASTUnit *TU) { assert(Class && TU && "Invalid arguments!"); void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding()); CXCursor C = { CXCursor_ObjCClassRef, { Class, RawLoc, TU } }; return C; }
CXCursor cxcursor::MakeCursorMemberRef(FieldDecl *Field, SourceLocation Loc, CXTranslationUnit TU) { assert(Field && TU && "Invalid arguments!"); void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding()); CXCursor C = { CXCursor_MemberRef, { Field, RawLoc, TU } }; return C; }
CXCursor cxcursor::MakeCursorNamespaceRef(NamedDecl *NS, SourceLocation Loc, CXTranslationUnit TU) { assert(NS && (isa<NamespaceDecl>(NS) || isa<NamespaceAliasDecl>(NS)) && TU && "Invalid arguments!"); void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding()); CXCursor C = { CXCursor_NamespaceRef, { NS, RawLoc, TU } }; return C; }
CXIdxLoc CXIndexDataConsumer::getIndexLoc(SourceLocation Loc) const { CXIdxLoc idxLoc = { {nullptr, nullptr}, 0 }; if (Loc.isInvalid()) return idxLoc; idxLoc.ptr_data[0] = const_cast<CXIndexDataConsumer *>(this); idxLoc.int_data = Loc.getRawEncoding(); return idxLoc; }
CXIdxLoc IndexingContext::getIndexLoc(SourceLocation Loc) const { CXIdxLoc idxLoc = { {0, 0}, 0 }; if (Loc.isInvalid()) return idxLoc; idxLoc.ptr_data[0] = (void*)this; idxLoc.int_data = Loc.getRawEncoding(); return idxLoc; }
bool Sema::CheckCUDACall(SourceLocation Loc, FunctionDecl *Callee) { assert(getLangOpts().CUDA && "Should only be called during CUDA compilation"); assert(Callee && "Callee may not be null."); // FIXME: Is bailing out early correct here? Should we instead assume that // the caller is a global initializer? FunctionDecl *Caller = dyn_cast<FunctionDecl>(CurContext); if (!Caller) return true; // If the caller is known-emitted, mark the callee as known-emitted. // Otherwise, mark the call in our call graph so we can traverse it later. bool CallerKnownEmitted = IsKnownEmitted(*this, Caller); if (CallerKnownEmitted) MarkKnownEmitted(*this, Callee); else { // If we have // host fn calls kernel fn calls host+device, // the HD function does not get instantiated on the host. We model this by // omitting at the call to the kernel from the callgraph. This ensures // that, when compiling for host, only HD functions actually called from the // host get marked as known-emitted. if (getLangOpts().CUDAIsDevice || IdentifyCUDATarget(Callee) != CFT_Global) CUDACallGraph[Caller].insert(Callee); } CUDADiagBuilder::Kind DiagKind = [&] { switch (IdentifyCUDAPreference(Caller, Callee)) { case CFP_Never: return CUDADiagBuilder::K_Immediate; case CFP_WrongSide: assert(Caller && "WrongSide calls require a non-null caller"); // If we know the caller will be emitted, we know this wrong-side call // will be emitted, so it's an immediate error. Otherwise, defer the // error until we know the caller is emitted. return CallerKnownEmitted ? CUDADiagBuilder::K_Immediate : CUDADiagBuilder::K_Deferred; default: return CUDADiagBuilder::K_Nop; } }(); // Avoid emitting this error twice for the same location. Using a hashtable // like this is unfortunate, but because we must continue parsing as normal // after encountering a deferred error, it's otherwise very tricky for us to // ensure that we only emit this deferred error once. if (!LocsWithCUDACallDiags.insert(Loc.getRawEncoding()).second) return true; bool IsImmediateErr = CUDADiagBuilder(DiagKind, Loc, diag::err_ref_bad_target, Caller, *this) << IdentifyCUDATarget(Callee) << Callee << IdentifyCUDATarget(Caller); CUDADiagBuilder(DiagKind, Callee->getLocation(), diag::note_previous_decl, Caller, *this) << Callee; return !IsImmediateErr; }
CXCursor cxcursor::MakeCursorObjCClassRef(ObjCInterfaceDecl *Class, SourceLocation Loc, CXTranslationUnit TU) { // 'Class' can be null for invalid code. if (!Class) return MakeCXCursorInvalid(CXCursor_InvalidCode); assert(TU && "Invalid arguments!"); void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding()); CXCursor C = { CXCursor_ObjCClassRef, { Class, RawLoc, TU } }; return C; }
void UpgradeDurationConversionsCheck::check( const MatchFinder::MatchResult &Result) { const llvm::StringRef Message = "implicit conversion to 'int64_t' is deprecated in this context; use an " "explicit cast instead"; const auto *ArgExpr = Result.Nodes.getNodeAs<Expr>("arg"); SourceLocation Loc = ArgExpr->getBeginLoc(); if (!match(isInTemplateInstantiation(), *ArgExpr, *Result.Context).empty()) { if (MatchedTemplateLocations.count(Loc.getRawEncoding()) == 0) { // For each location matched in a template instantiation, we check if the // location can also be found in `MatchedTemplateLocations`. If it is not // found, that means the expression did not create a match without the // instantiation and depends on template parameters. A manual fix is // probably required so we provide only a warning. diag(Loc, Message); } return; } // We gather source locations from template matches not in template // instantiations for future matches. internal::Matcher<Stmt> IsInsideTemplate = hasAncestor(decl(anyOf(classTemplateDecl(), functionTemplateDecl()))); if (!match(IsInsideTemplate, *ArgExpr, *Result.Context).empty()) MatchedTemplateLocations.insert(Loc.getRawEncoding()); DiagnosticBuilder Diag = diag(Loc, Message); CharSourceRange SourceRange = Lexer::makeFileCharRange( CharSourceRange::getTokenRange(ArgExpr->getSourceRange()), *Result.SourceManager, Result.Context->getLangOpts()); if (SourceRange.isInvalid()) // An invalid source range likely means we are inside a macro body. A manual // fix is likely needed so we do not create a fix-it hint. return; Diag << FixItHint::CreateInsertion(SourceRange.getBegin(), "static_cast<int64_t>(") << FixItHint::CreateInsertion(SourceRange.getEnd(), ")"); }
CXCursor cxcursor::MakeCursorOverloadedDeclRef(TemplateName Name, SourceLocation Loc, CXTranslationUnit TU) { assert(Name.getAsOverloadedTemplate() && TU && "Invalid arguments!"); void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding()); OverloadedDeclRefStorage Storage(Name.getAsOverloadedTemplate()); CXCursor C = { CXCursor_OverloadedDeclRef, { Storage.getOpaqueValue(), RawLoc, TU } }; return C; }
void EditedSource::finishedCommit() { for (auto &ExpArg : CurrCommitMacroArgExps) { SourceLocation ExpLoc; IdentifierInfo *II; std::tie(ExpLoc, II) = ExpArg; auto &ArgNames = ExpansionToArgMap[ExpLoc.getRawEncoding()]; if (std::find(ArgNames.begin(), ArgNames.end(), II) == ArgNames.end()) { ArgNames.push_back(II); } } CurrCommitMacroArgExps.clear(); }
/// This should be called whenever the preprocessor encounters include /// directives. It does not say whether the file has been included, but it /// provides more information about the directive (hash location instead /// of location inside the included file). It is assumed that the matching /// FileChanged() or FileSkipped() is called after this. void InclusionRewriter::InclusionDirective(SourceLocation HashLoc, const Token &/*IncludeTok*/, StringRef /*FileName*/, bool /*IsAngled*/, const FileEntry * /*File*/, SourceLocation /*EndLoc*/, StringRef /*SearchPath*/, StringRef /*RelativePath*/) { assert(LastInsertedFileChange == FileChanges.end() && "Another inclusion " "directive was found before the previous one was processed"); std::pair<FileChangeMap::iterator, bool> p = FileChanges.insert( std::make_pair(HashLoc.getRawEncoding(), FileChange(HashLoc))); assert(p.second && "Unexpected revisitation of the same include directive"); LastInsertedFileChange = p.first; }
static void addUsage(IdentifierNamingCheck::NamingCheckFailureMap &Failures, const IdentifierNamingCheck::NamingCheckId &Decl, SourceRange Range, SourceManager *SourceMgr = nullptr) { // Do nothing if the provided range is invalid. if (Range.getBegin().isInvalid() || Range.getEnd().isInvalid()) return; // If we have a source manager, use it to convert to the spelling location for // performing the fix. This is necessary because macros can map the same // spelling location to different source locations, and we only want to fix // the token once, before it is expanded by the macro. SourceLocation FixLocation = Range.getBegin(); if (SourceMgr) FixLocation = SourceMgr->getSpellingLoc(FixLocation); if (FixLocation.isInvalid()) return; // Try to insert the identifier location in the Usages map, and bail out if it // is already in there auto &Failure = Failures[Decl]; if (!Failure.RawUsageLocs.insert(FixLocation.getRawEncoding()).second) return; if (!Failure.ShouldFix) return; // Check if the range is entirely contained within a macro argument. SourceLocation MacroArgExpansionStartForRangeBegin; SourceLocation MacroArgExpansionStartForRangeEnd; bool RangeIsEntirelyWithinMacroArgument = SourceMgr && SourceMgr->isMacroArgExpansion(Range.getBegin(), &MacroArgExpansionStartForRangeBegin) && SourceMgr->isMacroArgExpansion(Range.getEnd(), &MacroArgExpansionStartForRangeEnd) && MacroArgExpansionStartForRangeBegin == MacroArgExpansionStartForRangeEnd; // Check if the range contains any locations from a macro expansion. bool RangeContainsMacroExpansion = RangeIsEntirelyWithinMacroArgument || Range.getBegin().isMacroID() || Range.getEnd().isMacroID(); bool RangeCanBeFixed = RangeIsEntirelyWithinMacroArgument || !RangeContainsMacroExpansion; Failure.ShouldFix = RangeCanBeFixed; }
/// This should be called whenever the preprocessor encounters include /// directives. It does not say whether the file has been included, but it /// provides more information about the directive (hash location instead /// of location inside the included file). It is assumed that the matching /// FileChanged() or FileSkipped() is called after this. void InclusionRewriter::InclusionDirective(SourceLocation HashLoc, const Token &/*IncludeTok*/, StringRef /*FileName*/, bool /*IsAngled*/, CharSourceRange /*FilenameRange*/, const FileEntry * /*File*/, StringRef /*SearchPath*/, StringRef /*RelativePath*/, const Module *Imported) { assert(LastInclusionLocation.isInvalid() && "Another inclusion directive was found before the previous one " "was processed"); if (Imported) { auto P = ModuleIncludes.insert( std::make_pair(HashLoc.getRawEncoding(), Imported)); (void)P; assert(P.second && "Unexpected revisitation of the same include directive"); } else LastInclusionLocation = HashLoc; }
bool EditedSource::canInsertInOffset(SourceLocation OrigLoc, FileOffset Offs) { FileEditsTy::iterator FA = getActionForOffset(Offs); if (FA != FileEdits.end()) { if (FA->first != Offs) return false; // position has been removed. } if (SourceMgr.isMacroArgExpansion(OrigLoc)) { SourceLocation DefArgLoc = SourceMgr.getImmediateExpansionRange(OrigLoc).first; SourceLocation ExpLoc = SourceMgr.getImmediateExpansionRange(DefArgLoc).first; llvm::DenseMap<unsigned, SourceLocation>::iterator I = ExpansionToArgMap.find(ExpLoc.getRawEncoding()); if (I != ExpansionToArgMap.end() && I->second != DefArgLoc) return false; // Trying to write in a macro argument input that has // already been written for another argument of the same macro. } return true; }
/// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function. /// "TheDeclarator" is the declarator that this will be added to. DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isAmbiguous, SourceLocation LParenLoc, ParamInfo *Params, unsigned NumParams, SourceLocation EllipsisLoc, SourceLocation RParenLoc, unsigned TypeQuals, bool RefQualifierIsLvalueRef, SourceLocation RefQualifierLoc, SourceLocation ConstQualifierLoc, SourceLocation VolatileQualifierLoc, SourceLocation RestrictQualifierLoc, SourceLocation MutableLoc, ExceptionSpecificationType ESpecType, SourceLocation ESpecLoc, ParsedType *Exceptions, SourceRange *ExceptionRanges, unsigned NumExceptions, Expr *NoexceptExpr, CachedTokens *ExceptionSpecTokens, SourceLocation LocalRangeBegin, SourceLocation LocalRangeEnd, Declarator &TheDeclarator, TypeResult TrailingReturnType) { assert(!(TypeQuals & DeclSpec::TQ_atomic) && "function cannot have _Atomic qualifier"); DeclaratorChunk I; I.Kind = Function; I.Loc = LocalRangeBegin; I.EndLoc = LocalRangeEnd; I.Fun.AttrList = nullptr; I.Fun.hasPrototype = hasProto; I.Fun.isVariadic = EllipsisLoc.isValid(); I.Fun.isAmbiguous = isAmbiguous; I.Fun.LParenLoc = LParenLoc.getRawEncoding(); I.Fun.EllipsisLoc = EllipsisLoc.getRawEncoding(); I.Fun.RParenLoc = RParenLoc.getRawEncoding(); I.Fun.DeleteParams = false; I.Fun.TypeQuals = TypeQuals; I.Fun.NumParams = NumParams; I.Fun.Params = nullptr; I.Fun.RefQualifierIsLValueRef = RefQualifierIsLvalueRef; I.Fun.RefQualifierLoc = RefQualifierLoc.getRawEncoding(); I.Fun.ConstQualifierLoc = ConstQualifierLoc.getRawEncoding(); I.Fun.VolatileQualifierLoc = VolatileQualifierLoc.getRawEncoding(); I.Fun.RestrictQualifierLoc = RestrictQualifierLoc.getRawEncoding(); I.Fun.MutableLoc = MutableLoc.getRawEncoding(); I.Fun.ExceptionSpecType = ESpecType; I.Fun.ExceptionSpecLoc = ESpecLoc.getRawEncoding(); I.Fun.NumExceptions = 0; I.Fun.Exceptions = nullptr; I.Fun.NoexceptExpr = nullptr; I.Fun.HasTrailingReturnType = TrailingReturnType.isUsable() || TrailingReturnType.isInvalid(); I.Fun.TrailingReturnType = TrailingReturnType.get(); assert(I.Fun.TypeQuals == TypeQuals && "bitfield overflow"); assert(I.Fun.ExceptionSpecType == ESpecType && "bitfield overflow"); // new[] a parameter array if needed. if (NumParams) { // If the 'InlineParams' in Declarator is unused and big enough, put our // parameter list there (in an effort to avoid new/delete traffic). If it // is already used (consider a function returning a function pointer) or too // small (function with too many parameters), go to the heap. if (!TheDeclarator.InlineParamsUsed && NumParams <= llvm::array_lengthof(TheDeclarator.InlineParams)) { I.Fun.Params = TheDeclarator.InlineParams; I.Fun.DeleteParams = false; TheDeclarator.InlineParamsUsed = true; } else { I.Fun.Params = new DeclaratorChunk::ParamInfo[NumParams]; I.Fun.DeleteParams = true; } memcpy(I.Fun.Params, Params, sizeof(Params[0]) * NumParams); } // Check what exception specification information we should actually store. switch (ESpecType) { default: break; // By default, save nothing. case EST_Dynamic: // new[] an exception array if needed if (NumExceptions) { I.Fun.NumExceptions = NumExceptions; I.Fun.Exceptions = new DeclaratorChunk::TypeAndRange[NumExceptions]; for (unsigned i = 0; i != NumExceptions; ++i) { I.Fun.Exceptions[i].Ty = Exceptions[i]; I.Fun.Exceptions[i].Range = ExceptionRanges[i]; } } break; case EST_ComputedNoexcept: I.Fun.NoexceptExpr = NoexceptExpr; break; case EST_Unparsed: I.Fun.ExceptionSpecTokens = ExceptionSpecTokens; break; } return I; }
static void checkAllAtProps(MigrationContext &MigrateCtx, SourceLocation AtLoc, IndivPropsTy &IndProps) { if (IndProps.empty()) return; for (IndivPropsTy::iterator PI = IndProps.begin(), PE = IndProps.end(); PI != PE; ++PI) { QualType T = (*PI)->getType(); if (T.isNull() || !T->isObjCRetainableType()) return; } SmallVector<std::pair<AttributedTypeLoc, ObjCPropertyDecl *>, 4> ATLs; bool hasWeak = false, hasStrong = false; ObjCPropertyDecl::PropertyAttributeKind Attrs = ObjCPropertyDecl::OBJC_PR_noattr; for (IndivPropsTy::iterator PI = IndProps.begin(), PE = IndProps.end(); PI != PE; ++PI) { ObjCPropertyDecl *PD = *PI; Attrs = PD->getPropertyAttributesAsWritten(); TypeSourceInfo *TInfo = PD->getTypeSourceInfo(); if (!TInfo) return; TypeLoc TL = TInfo->getTypeLoc(); if (AttributedTypeLoc ATL = TL.getAs<AttributedTypeLoc>()) { ATLs.push_back(std::make_pair(ATL, PD)); if (TInfo->getType().getObjCLifetime() == Qualifiers::OCL_Weak) { hasWeak = true; } else if (TInfo->getType().getObjCLifetime() == Qualifiers::OCL_Strong) hasStrong = true; else return; } } if (ATLs.empty()) return; if (hasWeak && hasStrong) return; TransformActions &TA = MigrateCtx.Pass.TA; Transaction Trans(TA); if (GCAttrsCollector::hasObjCImpl( cast<Decl>(IndProps.front()->getDeclContext()))) { if (hasWeak) MigrateCtx.AtPropsWeak.insert(AtLoc.getRawEncoding()); } else { StringRef toAttr = "strong"; if (hasWeak) { if (canApplyWeak(MigrateCtx.Pass.Ctx, IndProps.front()->getType(), /*AllowOnUnkwownClass=*/true)) toAttr = "weak"; else toAttr = "unsafe_unretained"; } if (Attrs & ObjCPropertyDecl::OBJC_PR_assign) MigrateCtx.rewritePropertyAttribute("assign", toAttr, AtLoc); else MigrateCtx.addPropertyAttribute(toAttr, AtLoc); } for (unsigned i = 0, e = ATLs.size(); i != e; ++i) { SourceLocation Loc = ATLs[i].first.getAttrNameLoc(); if (Loc.isMacroID()) Loc = MigrateCtx.Pass.Ctx.getSourceManager() .getImmediateExpansionRange(Loc).first; TA.remove(Loc); TA.clearDiagnostic(diag::err_objc_property_attr_mutually_exclusive, AtLoc); TA.clearDiagnostic(diag::err_arc_inconsistent_property_ownership, ATLs[i].second->getLocation()); MigrateCtx.RemovedAttrSet.insert(Loc.getRawEncoding()); } }
void OMPPragmaHandler::HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, SourceRange IntroducerRange, Token &FirstTok) { Diags.Report(IntroducerRange.getBegin(), DiagFoundPragmaStmt); // TODO: Clean this up because I'm too lazy to now PragmaDirective * DirectivePointer = new PragmaDirective; PragmaDirective &Directive = *DirectivePointer; // First lex the pragma statement extracting the variable names SourceLocation Loc = IntroducerRange.getBegin(); Token Tok = FirstTok; StringRef ident = getIdentifier(Tok); if (ident != "omp") { LexUntil(PP, Tok, clang::tok::eod); return; } PP.Lex(Tok); ident = getIdentifier(Tok); bool isParallel = false; bool isThreadPrivate = false; if (ident == "parallel") { PragmaConstruct C; C.Type = ParallelConstruct; C.Range = getTokenRange(Tok, PP); Directive.insertConstruct(C); isParallel = true; } else if (ident == "sections" || ident == "section" || ident == "task" || ident == "taskyield" || ident == "taskwait" || ident == "atomic" || ident == "ordered") { Diags.Report(Tok.getLocation(), DiagUnsupportedConstruct); LexUntil(PP, Tok, clang::tok::eod); return; } else if (ident == "for") { PragmaConstruct C; C.Type = ForConstruct; C.Range = getTokenRange(Tok, PP); Directive.insertConstruct(C); } else if (ident == "threadprivate") { isThreadPrivate = true; PragmaConstruct C; C.Type = ThreadprivateConstruct; C.Range = getTokenRange(Tok, PP); Directive.insertConstruct(C); } else if (ident == "single") { PragmaConstruct C; C.Type = SingleConstruct; C.Range = getTokenRange(Tok, PP); Directive.insertConstruct(C); } else if (ident == "master") { PragmaConstruct C; C.Type = MasterConstruct; C.Range = getTokenRange(Tok, PP); Directive.insertConstruct(C); } else if (ident == "critical" || ident == "flush") { // Ignored Directive // (Critical, Flush) LexUntil(PP, Tok, clang::tok::eod); return; } else if (ident == "barrier") { PragmaConstruct C; C.Type = BarrierConstruct; C.Range = getTokenRange(Tok, PP); Directive.insertConstruct(C); } else { Diags.Report(Tok.getLocation(), DiagUnknownDirective); return; } if (!isThreadPrivate) { PP.Lex(Tok); } if (isParallel) { ident = getIdentifier(Tok); if (ident == "sections") { Diags.Report(Tok.getLocation(), DiagUnsupportedConstruct); LexUntil(PP, Tok, clang::tok::eod); return; } else if (ident == "for") { PragmaConstruct C; C.Type = ForConstruct; C.Range = getTokenRange(Tok, PP); Directive.insertConstruct(C); PP.Lex(Tok); } else { // Just a standard "#pragma omp parallel" clause if (Tok.isNot(clang::tok::eod) && PragmaDirective::getClauseType(ident) == UnknownClause) { Diags.Report(Tok.getLocation(), DiagUnknownClause); return; } } } // If we've made it this far then we either have: // "#pragma omp parallel", // "#pragma omp parallel for", // "#pragma omp for", // "#pragma omp threadprivate // Need to read in the options, if they exists // Don't really care about them unless there exists a private(...) list // In which case, get the variables inside that list // But we read them all in anyway. // There's also threadprivate, which won't have any clauses, but will have // a list of private variables just after the threadprivate directive // Treating threadprivate as a clause and directive at the same time. while(Tok.isNot(clang::tok::eod)) { PragmaClause C; ident = getIdentifier(Tok); C.Type = PragmaDirective::getClauseType(ident); if (C.Type == UnknownClause) { Diags.Report(Tok.getLocation(), DiagUnknownClause); return; } SourceLocation clauseStart = Tok.getLocation(); SourceLocation clauseEnd = PP.getLocForEndOfToken(clauseStart); PP.Lex(Tok); if (Tok.is(clang::tok::l_paren)) { if (!handleList(Tok, PP, C)) { Diags.Report(clauseStart, DiagMalformedStatement); LexUntil(PP, Tok, clang::tok::eod); return; } clauseEnd = PP.getLocForEndOfToken(Tok.getLocation()); // Eat the clang::tok::r_paren PP.Lex(Tok); } C.Range = SourceRange(clauseStart, clauseEnd); Directive.insertClause(C); } SourceLocation EndLoc = PP.getLocForEndOfToken(Tok.getLocation()); Directive.setRange(SourceRange(Loc, EndLoc)); Directives.insert(std::make_pair(Loc.getRawEncoding(), DirectivePointer)); // Then replace with parseable compound statement to catch in Sema, and // references to private variables; // { // i; // j; // k; // } // If it's a threadprivate directive, then we skip this completely if (isThreadPrivate) { return; } set<IdentifierInfo *> PrivateVars = Directive.getPrivateIdentifiers(); int tokenCount = 2 + 2 * PrivateVars.size(); int currentToken = 0; Token * Toks = new Token[tokenCount]; Toks[currentToken++] = createToken(Loc, clang::tok::l_brace); set<IdentifierInfo *>::iterator PrivIt; for (PrivIt = PrivateVars.begin(); PrivIt != PrivateVars.end(); PrivIt++) { Toks[currentToken++] = createToken(Loc, clang::tok::identifier, *PrivIt); Toks[currentToken++] = createToken(Loc, clang::tok::semi); } Toks[currentToken++] = createToken(EndLoc, clang::tok::r_brace); assert(currentToken == tokenCount); Diags.setDiagnosticGroupMapping("unused-value", clang::diag::MAP_IGNORE, Loc); Diags.setDiagnosticGroupMapping("unused-value", clang::diag::MAP_WARNING, EndLoc); PP.EnterTokenStream(Toks, tokenCount, true, true); }
static bool compare_vd_entries(const Decl *A, const Decl *B) { SourceLocation ALoc = A->getLocStart(); SourceLocation BLoc = B->getLocStart(); return ALoc.getRawEncoding() < BLoc.getRawEncoding(); }