本文整理汇总了C++中SourceLocation::getLocWithOffset方法的典型用法代码示例。如果您正苦于以下问题:C++ SourceLocation::getLocWithOffset方法的具体用法?C++ SourceLocation::getLocWithOffset怎么用?C++ SourceLocation::getLocWithOffset使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类SourceLocation
的用法示例。
在下文中一共展示了SourceLocation::getLocWithOffset方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: ParseDirective
/// ParseDirective - Go through the comment and see if it indicates expected
/// diagnostics. If so, then put them in the appropriate directive list.
///
/// Returns true if any valid directives were found.
static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM,
SourceLocation Pos, DiagnosticsEngine &Diags,
VerifyDiagnosticConsumer::DirectiveStatus &Status) {
// A single comment may contain multiple directives.
bool FoundDirective = false;
for (ParseHelper PH(S); !PH.Done();) {
// Search for token: expected
if (!PH.Search("expected", true))
break;
PH.Advance();
// Next token: -
if (!PH.Next("-"))
continue;
PH.Advance();
// Next token: { error | warning | note }
DirectiveList* DL = NULL;
if (PH.Next("error"))
DL = ED ? &ED->Errors : NULL;
else if (PH.Next("warning"))
DL = ED ? &ED->Warnings : NULL;
else if (PH.Next("note"))
DL = ED ? &ED->Notes : NULL;
else if (PH.Next("no-diagnostics")) {
if (Status == VerifyDiagnosticConsumer::HasOtherExpectedDirectives)
Diags.Report(Pos, diag::err_verify_invalid_no_diags)
<< /*IsExpectedNoDiagnostics=*/true;
else
Status = VerifyDiagnosticConsumer::HasExpectedNoDiagnostics;
continue;
} else
continue;
PH.Advance();
if (Status == VerifyDiagnosticConsumer::HasExpectedNoDiagnostics) {
Diags.Report(Pos, diag::err_verify_invalid_no_diags)
<< /*IsExpectedNoDiagnostics=*/false;
continue;
}
Status = VerifyDiagnosticConsumer::HasOtherExpectedDirectives;
// If a directive has been found but we're not interested
// in storing the directive information, return now.
if (!DL)
return true;
// Default directive kind.
bool RegexKind = false;
const char* KindStr = "string";
// Next optional token: -
if (PH.Next("-re")) {
PH.Advance();
RegexKind = true;
KindStr = "regex";
}
// Next optional token: @
SourceLocation ExpectedLoc;
if (!PH.Next("@")) {
ExpectedLoc = Pos;
} else {
PH.Advance();
unsigned Line = 0;
bool FoundPlus = PH.Next("+");
if (FoundPlus || PH.Next("-")) {
// Relative to current line.
PH.Advance();
bool Invalid = false;
unsigned ExpectedLine = SM.getSpellingLineNumber(Pos, &Invalid);
if (!Invalid && PH.Next(Line) && (FoundPlus || Line < ExpectedLine)) {
if (FoundPlus) ExpectedLine += Line;
else ExpectedLine -= Line;
ExpectedLoc = SM.translateLineCol(SM.getFileID(Pos), ExpectedLine, 1);
}
} else {
// Absolute line number.
if (PH.Next(Line) && Line > 0)
ExpectedLoc = SM.translateLineCol(SM.getFileID(Pos), Line, 1);
}
if (ExpectedLoc.isInvalid()) {
Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),
diag::err_verify_missing_line) << KindStr;
continue;
}
PH.Advance();
}
// Skip optional whitespace.
PH.SkipWhitespace();
// Next optional token: positive integer or a '+'.
unsigned Min = 1;
unsigned Max = 1;
//.........这里部分代码省略.........
示例2: Finish
//.........这里部分代码省略.........
// Validate the width of the type.
switch (TypeSpecWidth) {
case TSW_unspecified:
break;
case TSW_short: // short int
case TSW_longlong: // long long int
if (TypeSpecType == TST_unspecified)
TypeSpecType = TST_int; // short -> short int, long long -> long long int.
else if (TypeSpecType != TST_int) {
Diag(D, TSWLoc,
TypeSpecWidth == TSW_short ? diag::err_invalid_short_spec
: diag::err_invalid_longlong_spec)
<< getSpecifierName((TST)TypeSpecType);
TypeSpecType = TST_int;
TypeSpecOwned = false;
}
break;
case TSW_long: // long double, long int
if (TypeSpecType == TST_unspecified)
TypeSpecType = TST_int; // long -> long int.
else if (TypeSpecType != TST_int && TypeSpecType != TST_double) {
Diag(D, TSWLoc, diag::err_invalid_long_spec)
<< getSpecifierName((TST)TypeSpecType);
TypeSpecType = TST_int;
TypeSpecOwned = false;
}
break;
}
// TODO: if the implementation does not implement _Complex or _Imaginary,
// disallow their use. Need information about the backend.
if (TypeSpecComplex != TSC_unspecified) {
if (TypeSpecType == TST_unspecified) {
Diag(D, TSCLoc, diag::ext_plain_complex)
<< FixItHint::CreateInsertion(
PP.getLocForEndOfToken(getTypeSpecComplexLoc()),
" double");
TypeSpecType = TST_double; // _Complex -> _Complex double.
} else if (TypeSpecType == TST_int || TypeSpecType == TST_char) {
// Note that this intentionally doesn't include _Complex _Bool.
if (!PP.getLangOpts().CPlusPlus)
Diag(D, TSTLoc, diag::ext_integer_complex);
} else if (TypeSpecType != TST_float && TypeSpecType != TST_double) {
Diag(D, TSCLoc, diag::err_invalid_complex_spec)
<< getSpecifierName((TST)TypeSpecType);
TypeSpecComplex = TSC_unspecified;
}
}
// If no type specifier was provided and we're parsing a language where
// the type specifier is not optional, but we got 'auto' as a storage
// class specifier, then assume this is an attempt to use C++0x's 'auto'
// type specifier.
// FIXME: Does Microsoft really support implicit int in C++?
if (PP.getLangOpts().CPlusPlus && !PP.getLangOpts().MicrosoftExt &&
TypeSpecType == TST_unspecified && StorageClassSpec == SCS_auto) {
TypeSpecType = TST_auto;
StorageClassSpec = StorageClassSpecAsWritten = SCS_unspecified;
TSTLoc = TSTNameLoc = StorageClassSpecLoc;
StorageClassSpecLoc = SourceLocation();
}
// Diagnose if we've recovered from an ill-formed 'auto' storage class
// specifier in a pre-C++0x dialect of C++.
if (!PP.getLangOpts().CPlusPlus0x && TypeSpecType == TST_auto)
Diag(D, TSTLoc, diag::ext_auto_type_specifier);
if (PP.getLangOpts().CPlusPlus && !PP.getLangOpts().CPlusPlus0x &&
StorageClassSpec == SCS_auto)
Diag(D, StorageClassSpecLoc, diag::warn_auto_storage_class)
<< FixItHint::CreateRemoval(StorageClassSpecLoc);
if (TypeSpecType == TST_char16 || TypeSpecType == TST_char32)
Diag(D, TSTLoc, diag::warn_cxx98_compat_unicode_type)
<< (TypeSpecType == TST_char16 ? "char16_t" : "char32_t");
if (Constexpr_specified)
Diag(D, ConstexprLoc, diag::warn_cxx98_compat_constexpr);
// C++ [class.friend]p6:
// No storage-class-specifier shall appear in the decl-specifier-seq
// of a friend declaration.
if (isFriendSpecified() && getStorageClassSpec()) {
DeclSpec::SCS SC = getStorageClassSpec();
const char *SpecName = getSpecifierName(SC);
SourceLocation SCLoc = getStorageClassSpecLoc();
SourceLocation SCEndLoc = SCLoc.getLocWithOffset(strlen(SpecName));
Diag(D, SCLoc, diag::err_friend_storage_spec)
<< SpecName
<< FixItHint::CreateRemoval(SourceRange(SCLoc, SCEndLoc));
ClearStorageClassSpecs();
}
assert(!TypeSpecOwned || isDeclRep((TST) TypeSpecType));
// Okay, now we can infer the real type.
// TODO: return "auto function" and other bad things based on the real type.
// 'data definition has no type or storage class'?
}
示例3: if
// Add the input to the memory buffer, parse it, and add it to the AST.
IncrementalParser::EParseResult
IncrementalParser::Parse(llvm::StringRef input) {
Preprocessor& PP = m_CI->getPreprocessor();
DiagnosticConsumer& DClient = m_CI->getDiagnosticClient();
PP.enableIncrementalProcessing();
DClient.BeginSourceFile(m_CI->getLangOpts(), &PP);
// Reset the transaction information
getLastTransaction().setBeforeFirstDecl(getCI()->getSema().CurContext);
if (input.size()) {
std::ostringstream source_name;
source_name << "input_line_" << (m_MemoryBuffer.size() + 1);
llvm::MemoryBuffer* MB
= llvm::MemoryBuffer::getMemBufferCopy(input, source_name.str());
m_MemoryBuffer.push_back(MB);
SourceManager& SM = getCI()->getSourceManager();
// Create SourceLocation, which will allow clang to order the overload
// candidates for example
SourceLocation NewLoc = SM.getLocForStartOfFile(m_VirtualFileID);
NewLoc = NewLoc.getLocWithOffset(m_MemoryBuffer.size() + 1);
// Create FileID for the current buffer
FileID FID = SM.createFileIDForMemBuffer(m_MemoryBuffer.back(),
/*LoadedID*/0,
/*LoadedOffset*/0, NewLoc);
PP.EnterSourceFile(FID, 0, NewLoc);
}
Parser::DeclGroupPtrTy ADecl;
while (!m_Parser->ParseTopLevelDecl(ADecl)) {
// Not end of file.
// If we got a null return and something *was* parsed, ignore it. This
// is due to a top-level semicolon, an action override, or a parse error
// skipping something.
if (ADecl) {
DeclGroupRef DGR = ADecl.getAsVal<DeclGroupRef>();
for (DeclGroupRef::iterator i=DGR.begin(); i< DGR.end(); ++i) {
if (!m_FirstTopLevelDecl)
m_FirstTopLevelDecl = *((*i)->getDeclContext()->decls_begin());
m_LastTopLevelDecl = *i;
}
m_Consumer->HandleTopLevelDecl(DGR);
} // ADecl
};
// Process any TopLevelDecls generated by #pragma weak.
for (llvm::SmallVector<Decl*,2>::iterator
I = getCI()->getSema().WeakTopLevelDecls().begin(),
E = getCI()->getSema().WeakTopLevelDecls().end(); I != E; ++I) {
m_Consumer->HandleTopLevelDecl(DeclGroupRef(*I));
}
getCI()->getSema().PerformPendingInstantiations();
DClient.EndSourceFile();
PP.enableIncrementalProcessing(false);
DiagnosticsEngine& Diag = getCI()->getSema().getDiagnostics();
if (Diag.hasErrorOccurred())
return IncrementalParser::kFailed;
else if (Diag.getNumWarnings())
return IncrementalParser::kSuccessWithWarnings;
return IncrementalParser::kSuccess;
}
示例4: EndOfMainFile
void IncludeOrderPPCallbacks::EndOfMainFile() {
LookForMainModule = true;
if (IncludeDirectives.empty())
return;
// TODO: find duplicated includes.
// Form blocks of includes. We don't want to sort across blocks. This also
// implicitly makes us never reorder over #defines or #if directives.
// FIXME: We should be more careful about sorting below comments as we don't
// know if the comment refers to the next include or the whole block that
// follows.
std::vector<unsigned> Blocks(1, 0);
for (unsigned I = 1, E = IncludeDirectives.size(); I != E; ++I)
if (SM.getExpansionLineNumber(IncludeDirectives[I].Loc) !=
SM.getExpansionLineNumber(IncludeDirectives[I - 1].Loc) + 1)
Blocks.push_back(I);
Blocks.push_back(IncludeDirectives.size()); // Sentinel value.
// Get a vector of indices.
std::vector<unsigned> IncludeIndices;
for (unsigned I = 0, E = IncludeDirectives.size(); I != E; ++I)
IncludeIndices.push_back(I);
// Sort the includes. We first sort by priority, then lexicographically.
for (unsigned BI = 0, BE = Blocks.size() - 1; BI != BE; ++BI)
std::sort(IncludeIndices.begin() + Blocks[BI],
IncludeIndices.begin() + Blocks[BI + 1],
[this](unsigned LHSI, unsigned RHSI) {
IncludeDirective &LHS = IncludeDirectives[LHSI];
IncludeDirective &RHS = IncludeDirectives[RHSI];
int PriorityLHS =
getPriority(LHS.Filename, LHS.IsAngled, LHS.IsMainModule);
int PriorityRHS =
getPriority(RHS.Filename, RHS.IsAngled, RHS.IsMainModule);
return std::tie(PriorityLHS, LHS.Filename) <
std::tie(PriorityRHS, RHS.Filename);
});
// Emit a warning for each block and fixits for all changes within that block.
for (unsigned BI = 0, BE = Blocks.size() - 1; BI != BE; ++BI) {
// Find the first include that's not in the right position.
unsigned I, E;
for (I = Blocks[BI], E = Blocks[BI + 1]; I != E; ++I)
if (IncludeIndices[I] != I)
break;
if (I == E)
continue;
// Emit a warning.
auto D = Check.diag(IncludeDirectives[I].Loc,
"#includes are not sorted properly");
// Emit fix-its for all following includes in this block.
for (; I != E; ++I) {
if (IncludeIndices[I] == I)
continue;
const IncludeDirective &CopyFrom = IncludeDirectives[IncludeIndices[I]];
SourceLocation FromLoc = CopyFrom.Range.getBegin();
const char *FromData = SM.getCharacterData(FromLoc);
unsigned FromLen = std::strcspn(FromData, "\n");
StringRef FixedName(FromData, FromLen);
SourceLocation ToLoc = IncludeDirectives[I].Range.getBegin();
const char *ToData = SM.getCharacterData(ToLoc);
unsigned ToLen = std::strcspn(ToData, "\n");
auto ToRange =
CharSourceRange::getCharRange(ToLoc, ToLoc.getLocWithOffset(ToLen));
D << FixItHint::CreateReplacement(ToRange, FixedName);
}
}
IncludeDirectives.clear();
}
示例5: removeArgFromExpr
bool RewriteUtils::removeArgFromExpr(const Expr *E,
int ParamPos)
{
if (ParamPos >= static_cast<int>(getNumArgsWrapper(E)))
return true;
const Expr *Arg = getArgWrapper(E, ParamPos);
TransAssert(Arg && "Null arg!");
if (dyn_cast<CXXDefaultArgExpr>(Arg->IgnoreParenCasts()))
return true;
SourceRange ArgRange = Arg->getSourceRange();
int RangeSize = TheRewriter->getRangeSize(ArgRange);
if (RangeSize == -1)
return false;
SourceLocation StartLoc = ArgRange.getBegin();
unsigned int NumArgs = getNumArgsWrapper(E);
if ((ParamPos == 0) && ((NumArgs == 1) ||
((NumArgs > 1) &&
dyn_cast<CXXDefaultArgExpr>(
getArgWrapper(E, 1)->IgnoreParenCasts())))) {
// Note that ')' is included in ParamLocRange
return !(TheRewriter->RemoveText(ArgRange));
}
int LastArgPos = static_cast<int>(NumArgs - 1);
// The param is the last non-default parameter
if ((ParamPos == LastArgPos) ||
((ParamPos < LastArgPos) &&
dyn_cast<CXXDefaultArgExpr>(
getArgWrapper(E, ParamPos+1)->IgnoreParenCasts()))) {
int Offset = 0;
const char *StartBuf = SrcManager->getCharacterData(StartLoc);
TransAssert(StartBuf && "Invalid start buffer!");
while (*StartBuf != ',') {
StartBuf--;
Offset--;
}
SourceLocation NewStartLoc = StartLoc.getLocWithOffset(Offset);
return !(TheRewriter->RemoveText(NewStartLoc,
RangeSize - Offset));
}
// We cannot use SrcManager->getCharacterData(StartLoc) to get the buffer,
// because it returns the unmodified string. I've tried to use
// getEndlocationUntil(ArgRange, ",", ...) call, but still failed.
// Seems in some cases, it returns bad results for a complex case like:
// foo(...foo(...), ...)
// So I ended up with this ugly way - get the end loc from the next arg.
const Expr *NextArg = getArgWrapper(E, ParamPos+1);
SourceRange NextArgRange = NextArg->getSourceRange();
SourceLocation NextStartLoc = NextArgRange.getBegin();
const char *NextStartBuf = SrcManager->getCharacterData(NextStartLoc);
int Offset = 0;
while (*NextStartBuf != ',') {
NextStartBuf--;
Offset--;
}
SourceLocation NewEndLoc = NextStartLoc.getLocWithOffset(Offset);
return !TheRewriter->RemoveText(SourceRange(StartLoc, NewEndLoc));
}
示例6: fillRanges
static bool fillRanges(MemoryBuffer *Code,
std::vector<tooling::Range> &Ranges) {
IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
new vfs::InMemoryFileSystem);
FileManager Files(FileSystemOptions(), InMemoryFileSystem);
DiagnosticsEngine Diagnostics(
IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
new DiagnosticOptions);
SourceManager Sources(Diagnostics, Files);
FileID ID = createInMemoryFile("<irrelevant>", Code, Sources, Files,
InMemoryFileSystem.get());
if (!LineRanges.empty()) {
if (!Offsets.empty() || !Lengths.empty()) {
errs() << "error: cannot use -lines with -offset/-length\n";
return true;
}
for (unsigned i = 0, e = LineRanges.size(); i < e; ++i) {
unsigned FromLine, ToLine;
if (parseLineRange(LineRanges[i], FromLine, ToLine)) {
errs() << "error: invalid <start line>:<end line> pair\n";
return true;
}
if (FromLine > ToLine) {
errs() << "error: start line should be less than end line\n";
return true;
}
SourceLocation Start = Sources.translateLineCol(ID, FromLine, 1);
SourceLocation End = Sources.translateLineCol(ID, ToLine, UINT_MAX);
if (Start.isInvalid() || End.isInvalid())
return true;
unsigned Offset = Sources.getFileOffset(Start);
unsigned Length = Sources.getFileOffset(End) - Offset;
Ranges.push_back(tooling::Range(Offset, Length));
}
return false;
}
if (Offsets.empty())
Offsets.push_back(0);
if (Offsets.size() != Lengths.size() &&
!(Offsets.size() == 1 && Lengths.empty())) {
errs() << "error: number of -offset and -length arguments must match.\n";
return true;
}
for (unsigned i = 0, e = Offsets.size(); i != e; ++i) {
if (Offsets[i] >= Code->getBufferSize()) {
errs() << "error: offset " << Offsets[i] << " is outside the file\n";
return true;
}
SourceLocation Start =
Sources.getLocForStartOfFile(ID).getLocWithOffset(Offsets[i]);
SourceLocation End;
if (i < Lengths.size()) {
if (Offsets[i] + Lengths[i] > Code->getBufferSize()) {
errs() << "error: invalid length " << Lengths[i]
<< ", offset + length (" << Offsets[i] + Lengths[i]
<< ") is outside the file.\n";
return true;
}
End = Start.getLocWithOffset(Lengths[i]);
} else {
End = Sources.getLocForEndOfFile(ID);
}
unsigned Offset = Sources.getFileOffset(Start);
unsigned Length = Sources.getFileOffset(End) - Offset;
Ranges.push_back(tooling::Range(Offset, Length));
}
return false;
}
示例7: findLocationAfterSemi
/// \brief 'Loc' is the end of a statement range. This returns the location
/// immediately after the semicolon following the statement.
/// If no semicolon is found or the location is inside a macro, the returned
/// source location will be invalid.
SourceLocation findLocationAfterSemi(SourceLocation loc, ASTContext &Ctx) {
SourceLocation SemiLoc = findSemiAfterLocation(loc, Ctx);
if (SemiLoc.isInvalid())
return SourceLocation();
return SemiLoc.getLocWithOffset(1);
}
示例8: getCharRange
CharSourceRange Commit::Edit::getInsertFromRange(SourceManager &SM) const {
SourceLocation Loc = SM.getLocForStartOfFile(InsertFromRangeOffs.getFID());
Loc = Loc.getLocWithOffset(InsertFromRangeOffs.getOffset());
assert(Loc.isFileID());
return CharSourceRange::getCharRange(Loc, Loc.getLocWithOffset(Length));
}
示例9: processFunctionDecl
void TypeRenameTransform::processFunctionDecl(FunctionDecl *D)
{
// if no type source info, it's a void f(void) function
auto TSI = D->getTypeSourceInfo();
if (TSI) {
processTypeLoc(TSI->getTypeLoc());
}
// handle ctor name initializers
if (auto CD = dyn_cast<CXXConstructorDecl>(D)) {
auto BL = CD->getLocation();
std::string newName;
if (BL.isValid() && CD->getParent()->getLocation() != BL &&
nameMatches(CD->getParent(), newName, true)) {
renameLocation(BL, newName);
}
for (auto II = CD->init_begin(), IE = CD->init_end(); II != IE; ++II) {
if ((*II)->isBaseInitializer()) {
processTypeLoc((*II)->getBaseClassLoc());
}
auto X = (*II)->getInit();
if (X) {
processStmt(X);
}
}
}
// dtor
if (auto DD = dyn_cast<CXXDestructorDecl>(D)) {
// if parent matches
auto BL = DD->getLocation();
std::string newName;
auto P = DD->getParent();
if (BL.isValid() && P->getLocation() != BL &&
nameMatches(P, newName, true)) {
// can't use renameLocation since this is a tricky case
// need to use raw_identifier because Lexer::findLocationAfterToken
// performs a raw lexing
SourceLocation EL =
Lexer::findLocationAfterToken(BL, tok::raw_identifier,
sema->getSourceManager(),
sema->getLangOpts(), false);
// TODO: Find the right way to do this -- consider this a hack
// llvm::errs() << indent() << "dtor at: " << loc(BL) << ", locStart: " << loc(DD->getLocStart())
// << ", nameAsString: " << P->getNameAsString() << ", len: " << P->getNameAsString().size()
// << ", DD nameAsString: " << DD->getNameAsString() << ", len: " << DD->getNameAsString().size()
// << "\n";
if (EL.isValid()) {
// EL is 1 char after the dtor name ~Foo, so -1 == pos of 'o'
SourceLocation NE = EL.getLocWithOffset(-1);
// we use the parent's name to see how much we should back off
// if we use D->getNameAsString(), we'd run into two problems:
// (1) the name would be ~Foo
// (2) the name for template class dtor would be ~Foo<T>
SourceLocation NB =
EL.getLocWithOffset(-(int)P->getNameAsString().size());
if (NB.isMacroID()) {
// TODO: emit error
llvm::errs() << "Warning: Token is resulted from macro expansion"
" and is therefore not renamed, at: " << loc(NB) << "\n";
}
else {
// TODO: Determine if it's a wrtiable file
// TODO: Determine if the location has already been touched or
// needs skipping (such as in refactoring API user's code, then
// the API headers need no changing since later the new API will be
// in place)
replace(SourceRange(NB, NE), newName);
}
}
}
}
// rename the params' types
for (auto PI = D->param_begin(), PE = D->param_end(); PI != PE; ++PI) {
processParmVarDecl(*PI);
}
// the name itself
processQualifierLoc(D->getQualifierLoc());
// handle body
if (auto B = D->getBody()) {
if (stmtInSameFileAsDecl(B, D)) {
// llvm::errs() << indent() << "body? " << D->getBody() << "\n";
processStmt(B);
}
}
//.........这里部分代码省略.........
示例10: assert
SourceLocation Commit::Edit::getFileLocation(SourceManager &SM) const {
SourceLocation Loc = SM.getLocForStartOfFile(Offset.getFID());
Loc = Loc.getLocWithOffset(Offset.getOffset());
assert(Loc.isFileID());
return Loc;
}
示例11: ActOnCompoundStmt
clang::StmtResult InsiemeSema::ActOnCompoundStmt(clang::SourceLocation L, clang::SourceLocation R, llvm::ArrayRef<clang::Stmt*> Elts, bool isStmtExpr) {
// we parse the original code segment, within the original locations
StmtResult&& ret = Sema::ActOnCompoundStmt(L, R, std::move(Elts), isStmtExpr);
clang::CompoundStmt* CS = cast<clang::CompoundStmt>(ret.get());
// This is still buggy as of Clang 3.6.2:
// when pragmas are just after the beginning of a compound stmt, example:
// {
// #pragma xxx
// ...
// }
// the location of the opening bracket is wrong because of a bug in the clang parser.
//
// We solve the problem by searching for the bracket in the input stream and overwrite
// the value of L (which contains the wrong location) with the correct value.
enum { MacroIDBit = 1U << 31 }; // from clang/Basic/SourceLocation.h for use with cpp classes
{
SourceLocation&& leftBracketLoc = SourceMgr.getImmediateSpellingLoc(L);
std::pair<FileID, unsigned>&& locInfo = SourceMgr.getDecomposedLoc(leftBracketLoc);
llvm::StringRef&& buffer = SourceMgr.getBufferData(locInfo.first);
const char* strData = buffer.begin() + locInfo.second;
char const* lBracePos = strbchr(strData, buffer.begin(), '{');
// We know the location of the left bracket, we overwrite the value of L with the correct location
// but only if the location is valid as in getFileLocWithOffset() in SourceLocation
if((((leftBracketLoc.getRawEncoding() & ~MacroIDBit) + (lBracePos - strData)) & MacroIDBit) == 0) {
L = leftBracketLoc.getLocWithOffset(lBracePos - strData);
}
}
// For the right bracket, we start at the final statement in the compound
// (or its start if it is empty) and search forward until we find the first "}"
// Otherwise, cases such as this:
//
// {
// bla();
// }
// #pragma test expect_ir(R"( {} )")
//
// will be broken
{
SourceLocation rightBracketLoc;
if(CS->size() == 0) {
rightBracketLoc = SourceMgr.getImmediateSpellingLoc(L);
} else {
rightBracketLoc = SourceMgr.getImmediateSpellingLoc(CS->body_back()->getLocEnd());
}
std::pair<FileID, unsigned>&& locInfo = SourceMgr.getDecomposedLoc(rightBracketLoc);
llvm::StringRef buffer = SourceMgr.getBufferData(locInfo.first);
const char* strData = buffer.begin() + locInfo.second;
char const* rBracePos = strchr(strData, '}');
// We know the location of the right bracket, we overwrite the value of R with the correct location
if((((rightBracketLoc.getRawEncoding() & ~MacroIDBit) + (rBracePos - strData)) & MacroIDBit) == 0) {
R = rightBracketLoc.getLocWithOffset(rBracePos - strData);
}
}
// the source range we inspect is defined by the new source locations,
// this fix the problem with boundaries jumping to the beginning of the file in
// the macro expansions:
//
// #define F(x) { }
//
// ...
//
// F(r) // <-this statement will jum to the macro location
//
PragmaList matched;
SourceRange SR(L, R);
// for each of the pragmas in the range between brackets
for(PragmaFilter&& filter = PragmaFilter(SR, SourceMgr, pimpl->pending_pragma); *filter; ++filter) {
PragmaPtr P = *filter;
unsigned int pragmaStart = utils::Line(P->getStartLocation(), SourceMgr);
unsigned int pragmaEnd = utils::Line(P->getEndLocation(), SourceMgr);
bool found = false;
// problem with first pragma, compound start is delayed until fist usable line (first stmt)
if(CS->size() > 0) {
for(clang::CompoundStmt::body_iterator it = CS->body_begin(); it != CS->body_end(); ++it) {
unsigned int stmtStart = (Line((*it)->getLocStart(), SourceMgr));
if((pragmaEnd <= stmtStart)) {
// ACHTUNG: if the node is a nullStmt, and is not at the end of the compound (in
// which case is most probably ours) we can not trust it. semantics wont change,
// we move one more. (BUG: nullStmt followed by pragmas, the source begin is
// postponed until next stmt) this makes pragmas to be attached to a previous
// stmt
if(!llvm::isa<clang::NullStmt>(*it)) {
// this pragma is attached to the current stmt
P->setStatement(*it);
matched.push_back(P);
found = true;
break;
}
}
//.........这里部分代码省略.........
示例12: check
void NamespaceCommentCheck::check(const MatchFinder::MatchResult &Result) {
const NamespaceDecl *ND = Result.Nodes.getNodeAs<NamespaceDecl>("namespace");
const SourceManager &Sources = *Result.SourceManager;
if (!locationsInSameFile(Sources, ND->getLocStart(), ND->getRBraceLoc()))
return;
// Don't require closing comments for namespaces spanning less than certain
// number of lines.
unsigned StartLine = Sources.getSpellingLineNumber(ND->getLocStart());
unsigned EndLine = Sources.getSpellingLineNumber(ND->getRBraceLoc());
if (EndLine - StartLine + 1 <= ShortNamespaceLines)
return;
// Find next token after the namespace closing brace.
SourceLocation AfterRBrace = ND->getRBraceLoc().getLocWithOffset(1);
SourceLocation Loc = AfterRBrace;
Token Tok;
// Skip whitespace until we find the next token.
while (Lexer::getRawToken(Loc, Tok, Sources, Result.Context->getLangOpts())) {
Loc = Loc.getLocWithOffset(1);
}
if (!locationsInSameFile(Sources, ND->getRBraceLoc(), Loc))
return;
bool NextTokenIsOnSameLine = Sources.getSpellingLineNumber(Loc) == EndLine;
// If we insert a line comment before the token in the same line, we need
// to insert a line break.
bool NeedLineBreak = NextTokenIsOnSameLine && Tok.isNot(tok::eof);
SourceRange OldCommentRange(AfterRBrace, AfterRBrace);
std::string Message = "%0 not terminated with a closing comment";
// Try to find existing namespace closing comment on the same line.
if (Tok.is(tok::comment) && NextTokenIsOnSameLine) {
StringRef Comment(Sources.getCharacterData(Loc), Tok.getLength());
SmallVector<StringRef, 7> Groups;
if (NamespaceCommentPattern.match(Comment, &Groups)) {
StringRef NamespaceNameInComment = Groups.size() > 5 ? Groups[5] : "";
StringRef Anonymous = Groups.size() > 3 ? Groups[3] : "";
// Check if the namespace in the comment is the same.
if ((ND->isAnonymousNamespace() && NamespaceNameInComment.empty()) ||
(ND->getNameAsString() == NamespaceNameInComment &&
Anonymous.empty())) {
// FIXME: Maybe we need a strict mode, where we always fix namespace
// comments with different format.
return;
}
// Otherwise we need to fix the comment.
NeedLineBreak = Comment.startswith("/*");
OldCommentRange =
SourceRange(AfterRBrace, Loc.getLocWithOffset(Tok.getLength()));
Message =
(llvm::Twine(
"%0 ends with a comment that refers to a wrong namespace '") +
NamespaceNameInComment + "'").str();
} else if (Comment.startswith("//")) {
// Assume that this is an unrecognized form of a namespace closing line
// comment. Replace it.
NeedLineBreak = false;
OldCommentRange =
SourceRange(AfterRBrace, Loc.getLocWithOffset(Tok.getLength()));
Message = "%0 ends with an unrecognized comment";
}
// If it's a block comment, just move it to the next line, as it can be
// multi-line or there may be other tokens behind it.
}
std::string NamespaceName =
ND->isAnonymousNamespace()
? "anonymous namespace"
: ("namespace '" + ND->getNameAsString() + "'");
diag(AfterRBrace, Message)
<< NamespaceName << FixItHint::CreateReplacement(
CharSourceRange::getCharRange(OldCommentRange),
std::string(SpacesBeforeComments, ' ') +
getNamespaceComment(ND, NeedLineBreak));
diag(ND->getLocation(), "%0 starts here", DiagnosticIDs::Note)
<< NamespaceName;
}
示例13: getLastMemoryBufferEndLoc
SourceLocation IncrementalParser::getLastMemoryBufferEndLoc() const {
const SourceManager& SM = getCI()->getSourceManager();
SourceLocation Result = SM.getLocForStartOfFile(m_VirtualFileID);
return Result.getLocWithOffset(m_MemoryBuffers.size() + 1);
}
示例14: if
// Add the input to the memory buffer, parse it, and add it to the AST.
IncrementalParser::EParseResult
IncrementalParser::ParseInternal(llvm::StringRef input) {
if (input.empty()) return IncrementalParser::kSuccess;
Sema& S = getCI()->getSema();
assert(!(S.getLangOpts().Modules
&& m_Consumer->getTransaction()->getCompilationOpts()
.CodeGenerationForModule)
&& "CodeGenerationForModule should be removed once modules are available!");
// Recover resources if we crash before exiting this method.
llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(&S);
Preprocessor& PP = m_CI->getPreprocessor();
if (!PP.getCurrentLexer()) {
PP.EnterSourceFile(m_CI->getSourceManager().getMainFileID(),
0, SourceLocation());
}
assert(PP.isIncrementalProcessingEnabled() && "Not in incremental mode!?");
PP.enableIncrementalProcessing();
std::ostringstream source_name;
source_name << "input_line_" << (m_MemoryBuffers.size() + 1);
// Create an uninitialized memory buffer, copy code in and append "\n"
size_t InputSize = input.size(); // don't include trailing 0
// MemBuffer size should *not* include terminating zero
llvm::MemoryBuffer* MB
= llvm::MemoryBuffer::getNewUninitMemBuffer(InputSize + 1,
source_name.str());
char* MBStart = const_cast<char*>(MB->getBufferStart());
memcpy(MBStart, input.data(), InputSize);
memcpy(MBStart + InputSize, "\n", 2);
m_MemoryBuffers.push_back(MB);
SourceManager& SM = getCI()->getSourceManager();
// Create SourceLocation, which will allow clang to order the overload
// candidates for example
SourceLocation NewLoc = SM.getLocForStartOfFile(m_VirtualFileID);
NewLoc = NewLoc.getLocWithOffset(m_MemoryBuffers.size() + 1);
// Create FileID for the current buffer
FileID FID = SM.createFileIDForMemBuffer(m_MemoryBuffers.back(),
SrcMgr::C_User,
/*LoadedID*/0,
/*LoadedOffset*/0, NewLoc);
PP.EnterSourceFile(FID, /*DirLookup*/0, NewLoc);
Parser::DeclGroupPtrTy ADecl;
while (!m_Parser->ParseTopLevelDecl(ADecl)) {
// If we got a null return and something *was* parsed, ignore it. This
// is due to a top-level semicolon, an action override, or a parse error
// skipping something.
if (ADecl)
m_Consumer->HandleTopLevelDecl(ADecl.getAsVal<DeclGroupRef>());
};
// Process any TopLevelDecls generated by #pragma weak.
for (llvm::SmallVector<Decl*,2>::iterator I = S.WeakTopLevelDecls().begin(),
E = S.WeakTopLevelDecls().end(); I != E; ++I) {
m_Consumer->HandleTopLevelDecl(DeclGroupRef(*I));
}
DiagnosticsEngine& Diag = S.getDiagnostics();
if (Diag.hasErrorOccurred())
return IncrementalParser::kFailed;
else if (Diag.getNumWarnings())
return IncrementalParser::kSuccessWithWarnings;
return IncrementalParser::kSuccess;
}
示例15: format
static void format() {
FileManager Files((FileSystemOptions()));
DiagnosticsEngine Diagnostics(
IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
new DiagnosticOptions);
SourceManager Sources(Diagnostics, Files);
OwningPtr<MemoryBuffer> Code;
if (error_code ec = MemoryBuffer::getFileOrSTDIN(FileName, Code)) {
llvm::errs() << ec.message() << "\n";
return;
}
FileID ID = createInMemoryFile(FileName, Code.get(), Sources, Files);
Lexer Lex(ID, Sources.getBuffer(ID), Sources, getFormattingLangOpts());
if (Offsets.empty())
Offsets.push_back(0);
if (Offsets.size() != Lengths.size() &&
!(Offsets.size() == 1 && Lengths.empty())) {
llvm::errs() << "Number of -offset and -length arguments must match.\n";
return;
}
std::vector<CharSourceRange> Ranges;
for (cl::list<int>::size_type i = 0, e = Offsets.size(); i != e; ++i) {
SourceLocation Start =
Sources.getLocForStartOfFile(ID).getLocWithOffset(Offsets[i]);
SourceLocation End;
if (i < Lengths.size()) {
End = Start.getLocWithOffset(Lengths[i]);
} else {
End = Sources.getLocForEndOfFile(ID);
}
Ranges.push_back(CharSourceRange::getCharRange(Start, End));
}
tooling::Replacements Replaces = reformat(getStyle(), Lex, Sources, Ranges);
if (OutputXML) {
llvm::outs() << "<?xml version='1.0'?>\n<replacements xml:space='preserve'>\n";
for (tooling::Replacements::const_iterator I = Replaces.begin(),
E = Replaces.end();
I != E; ++I) {
llvm::outs() << "<replacement "
<< "offset='" << I->getOffset() << "' "
<< "length='" << I->getLength() << "'>"
<< I->getReplacementText() << "</replacement>\n";
}
llvm::outs() << "</replacements>\n";
} else {
Rewriter Rewrite(Sources, LangOptions());
tooling::applyAllReplacements(Replaces, Rewrite);
if (Inplace) {
if (Replaces.size() == 0)
return; // Nothing changed, don't touch the file.
std::string ErrorInfo;
llvm::raw_fd_ostream FileStream(FileName.c_str(), ErrorInfo,
llvm::raw_fd_ostream::F_Binary);
if (!ErrorInfo.empty()) {
llvm::errs() << "Error while writing file: " << ErrorInfo << "\n";
return;
}
Rewrite.getEditBuffer(ID).write(FileStream);
FileStream.flush();
} else {
Rewrite.getEditBuffer(ID).write(outs());
}
}
}