1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
16 #include "clang/AST/Attr.h"
24 bool isSalBool(QualType type
) {
25 TypedefType
const * t
= type
->getAs
<TypedefType
>();
26 return t
!= nullptr && t
->getDecl()->getNameAsString() == "sal_Bool";
29 bool isSalBoolArray(QualType type
) {
30 auto t
= type
->getAsArrayTypeUnsafe();
32 && (isSalBool(t
->getElementType())
33 || isSalBoolArray(t
->getElementType()));
36 // It appears that, given a function declaration, there is no way to determine
37 // the language linkage of the function's type, only of the function's name
38 // (via FunctionDecl::isExternC); however, in a case like
40 // extern "C" { static void f(); }
42 // the function's name does not have C language linkage while the function's
43 // type does (as clarified in C++11 [decl.link]); cf. <http://clang-developers.
44 // 42468.n3.nabble.com/Language-linkage-of-function-type-tt4037248.html>
45 // "Language linkage of function type":
46 bool hasCLanguageLinkageType(FunctionDecl
const * decl
) {
47 assert(decl
!= nullptr);
48 if (decl
->isExternC()) {
51 if (decl
->isInExternCContext()) {
57 enum class OverrideKind
{ NO
, YES
, MAYBE
};
59 OverrideKind
getOverrideKind(FunctionDecl
const * decl
) {
60 CXXMethodDecl
const * m
= dyn_cast
<CXXMethodDecl
>(decl
);
62 return OverrideKind::NO
;
64 if (m
->size_overridden_methods() != 0 || m
->hasAttr
<OverrideAttr
>()) {
65 return OverrideKind::YES
;
67 if (!dyn_cast
<CXXRecordDecl
>(m
->getDeclContext())->hasAnyDependentBases()) {
68 return OverrideKind::NO
;
70 return OverrideKind::MAYBE
;
73 //TODO: current implementation is not at all general, just tests what we
74 // encounter in practice:
75 bool hasBoolOverload(FunctionDecl
const * decl
, bool mustBeDeleted
) {
76 unsigned n
= decl
->getNumParams();
77 auto res
= decl
->getDeclContext()->lookup(decl
->getDeclName());
78 for (auto d
= res
.begin(); d
!= res
.end(); ++d
) {
79 FunctionDecl
const * f
= dyn_cast
<FunctionDecl
>(*d
);
80 if (f
!= nullptr && (!mustBeDeleted
|| f
->isDeleted())) {
81 if (f
->getNumParams() == n
) {
83 for (unsigned i
= 0; i
!= n
; ++i
) {
84 QualType t1
{ decl
->getParamDecl(i
)->getType() };
85 bool isSB
= isSalBool(t1
);
86 bool isSBRef
= !isSB
&& t1
->isReferenceType()
87 && isSalBool(t1
.getNonReferenceType());
88 QualType t2
{ f
->getParamDecl(i
)->getType() };
92 ? (t2
->isReferenceType()
93 && t2
.getNonReferenceType()->isBooleanType())
98 hasSB
|= isSB
|| isSBRef
;
101 // cheaply protect against the case where decl would have no
102 // sal_Bool parameters at all and would match itself
111 public RecursiveASTVisitor
<SalBool
>, public loplugin::RewritePlugin
114 explicit SalBool(InstantiationData
const & data
): RewritePlugin(data
) {}
116 virtual void run() override
;
118 bool VisitUnaryAddrOf(UnaryOperator
const * op
);
120 bool VisitCallExpr(CallExpr
* expr
);
122 bool VisitCStyleCastExpr(CStyleCastExpr
* expr
);
124 bool VisitCXXStaticCastExpr(CXXStaticCastExpr
* expr
);
126 bool VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr
* expr
);
128 bool VisitImplicitCastExpr(ImplicitCastExpr
* expr
);
130 bool VisitReturnStmt(ReturnStmt
const * stmt
);
132 bool WalkUpFromParmVarDecl(ParmVarDecl
const * decl
);
133 bool VisitParmVarDecl(ParmVarDecl
const * decl
);
135 bool WalkUpFromVarDecl(VarDecl
const * decl
);
136 bool VisitVarDecl(VarDecl
const * decl
);
138 bool WalkUpFromFieldDecl(FieldDecl
const * decl
);
139 bool VisitFieldDecl(FieldDecl
const * decl
);
141 bool WalkUpFromFunctionDecl(FunctionDecl
const * decl
);
142 bool VisitFunctionDecl(FunctionDecl
const * decl
);
144 bool VisitValueDecl(ValueDecl
const * decl
);
146 bool TraverseStaticAssertDecl(StaticAssertDecl
* decl
);
148 bool TraverseLinkageSpecDecl(LinkageSpecDecl
* decl
);
151 bool isFromCIncludeFile(SourceLocation spellingLocation
) const;
153 bool isSharedCAndCppCode(SourceLocation location
) const;
155 bool isInSpecialMainFile(SourceLocation spellingLocation
) const;
157 bool rewrite(SourceLocation location
);
159 std::set
<VarDecl
const *> varDecls_
;
160 unsigned int externCContexts_
= 0;
163 void SalBool::run() {
164 if (compiler
.getLangOpts().CPlusPlus
) {
165 TraverseDecl(compiler
.getASTContext().getTranslationUnitDecl());
166 for (auto decl
: varDecls_
) {
167 SourceLocation loc
{ decl
->getLocStart() };
168 TypeSourceInfo
* tsi
= decl
->getTypeSourceInfo();
169 if (tsi
!= nullptr) {
171 compiler
.getSourceManager().getExpansionLoc(
172 tsi
->getTypeLoc().getBeginLoc()) };
174 compiler
.getSourceManager().getExpansionLoc(
175 tsi
->getTypeLoc().getEndLoc()) };
176 assert(l
.isFileID() && end
.isFileID());
178 || compiler
.getSourceManager().isBeforeInTranslationUnit(
182 unsigned n
= Lexer::MeasureTokenLength(
183 l
, compiler
.getSourceManager(),
184 compiler
.getLangOpts());
186 compiler
.getSourceManager().getCharacterData(l
),
188 if (s
== "sal_Bool") {
195 l
= l
.getLocWithOffset(std::max
<unsigned>(n
, 1));
201 DiagnosticsEngine::Warning
,
202 "VarDecl, use \"bool\" instead of \"sal_Bool\"", loc
)
203 << decl
->getSourceRange();
209 bool SalBool::VisitUnaryAddrOf(UnaryOperator
const * op
) {
210 Expr
const * e1
= op
->getSubExpr()->IgnoreParenCasts();
211 if (isSalBool(e1
->getType())) {
212 DeclRefExpr
const * e2
= dyn_cast
<DeclRefExpr
>(e1
);
214 VarDecl
const * d
= dyn_cast
<VarDecl
>(e2
->getDecl());
223 bool SalBool::VisitCallExpr(CallExpr
* expr
) {
224 Decl
const * d
= expr
->getCalleeDecl();
225 FunctionProtoType
const * ft
= nullptr;
227 FunctionDecl
const * fd
= dyn_cast
<FunctionDecl
>(d
);
229 PointerType
const * pt
= fd
->getType()->getAs
<PointerType
>();
230 QualType
t2(pt
== nullptr ? fd
->getType() : pt
->getPointeeType());
231 ft
= t2
->getAs
<FunctionProtoType
>();
233 ft
!= nullptr || !compiler
.getLangOpts().CPlusPlus
234 || (fd
->getBuiltinID() != Builtin::NotBuiltin
235 && isa
<FunctionNoProtoType
>(t2
)));
236 // __builtin_*s have no proto type?
238 VarDecl
const * vd
= dyn_cast
<VarDecl
>(d
);
240 PointerType
const * pt
= vd
->getType()->getAs
<PointerType
>();
241 ft
= (pt
== nullptr ? vd
->getType() : pt
->getPointeeType())
242 ->getAs
<FunctionProtoType
>();
247 for (unsigned i
= 0; i
!= compat::getNumParams(*ft
); ++i
) {
248 QualType
t(compat::getParamType(*ft
, i
));
250 if (t
->isLValueReferenceType()) {
251 t
= t
.getNonReferenceType();
252 b
= !t
.isConstQualified() && isSalBool(t
);
253 } else if (t
->isPointerType()) {
255 auto t2
= t
->getAs
<PointerType
>();
259 t
= t2
->getPointeeType();
263 if (b
&& i
< expr
->getNumArgs()) {
264 DeclRefExpr
* ref
= dyn_cast
<DeclRefExpr
>(
265 expr
->getArg(i
)->IgnoreParenImpCasts());
266 if (ref
!= nullptr) {
267 VarDecl
const * d
= dyn_cast
<VarDecl
>(ref
->getDecl());
278 bool SalBool::VisitCStyleCastExpr(CStyleCastExpr
* expr
) {
279 if (ignoreLocation(expr
)) {
282 if (isSalBool(expr
->getType())) {
283 SourceLocation loc
{ expr
->getLocStart() };
284 while (compiler
.getSourceManager().isMacroArgExpansion(loc
)) {
285 loc
= compiler
.getSourceManager().getImmediateMacroCallerLoc(loc
);
287 if (compiler
.getSourceManager().isMacroBodyExpansion(loc
)) {
288 StringRef name
{ Lexer::getImmediateMacroName(
289 loc
, compiler
.getSourceManager(), compiler
.getLangOpts()) };
290 if (name
== "sal_False" || name
== "sal_True") {
291 auto callLoc
= compiler
.getSourceManager()
292 .getImmediateMacroCallerLoc(loc
);
293 if (!isSharedCAndCppCode(callLoc
)) {
294 SourceLocation argLoc
;
295 if (compat::isMacroArgExpansion(
296 compiler
, expr
->getLocStart(), &argLoc
)
297 //TODO: check it's the complete (first) arg to the macro
298 && (Lexer::getImmediateMacroName(
299 argLoc
, compiler
.getSourceManager(),
300 compiler
.getLangOpts())
301 == "CPPUNIT_ASSERT_EQUAL"))
303 // Ignore sal_False/True that are directly used as
304 // arguments to CPPUNIT_ASSERT_EQUAL:
307 bool b
= name
== "sal_True";
308 if (rewriter
!= nullptr) {
309 auto callSpellLoc
= compiler
.getSourceManager()
310 .getSpellingLoc(callLoc
);
311 unsigned n
= Lexer::MeasureTokenLength(
312 callSpellLoc
, compiler
.getSourceManager(),
313 compiler
.getLangOpts());
315 compiler
.getSourceManager().getCharacterData(
321 callSpellLoc
, n
, b
? "true" : "false");
325 DiagnosticsEngine::Warning
,
326 "use '%select{false|true}0' instead of '%1'", callLoc
)
327 << b
<< name
<< expr
->getSourceRange();
333 DiagnosticsEngine::Warning
,
334 "CStyleCastExpr, suspicious cast from %0 to %1",
336 << expr
->getSubExpr()->IgnoreParenImpCasts()->getType()
337 << expr
->getType() << expr
->getSourceRange();
342 bool SalBool::VisitCXXStaticCastExpr(CXXStaticCastExpr
* expr
) {
343 if (ignoreLocation(expr
)) {
346 if (isSalBool(expr
->getType())
347 && !isInSpecialMainFile(
348 compiler
.getSourceManager().getSpellingLoc(expr
->getLocStart())))
351 DiagnosticsEngine::Warning
,
352 "CXXStaticCastExpr, suspicious cast from %0 to %1",
354 << expr
->getSubExpr()->IgnoreParenImpCasts()->getType()
355 << expr
->getType() << expr
->getSourceRange();
360 bool SalBool::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr
* expr
) {
361 if (ignoreLocation(expr
)) {
364 if (isSalBool(expr
->getType())) {
366 DiagnosticsEngine::Warning
,
367 "CXXFunctionalCastExpr, suspicious cast from %0 to %1",
369 << expr
->getSubExpr()->IgnoreParenImpCasts()->getType()
370 << expr
->getType() << expr
->getSourceRange();
375 bool SalBool::VisitImplicitCastExpr(ImplicitCastExpr
* expr
) {
376 if (ignoreLocation(expr
)) {
379 if (!isSalBool(expr
->getType())) {
382 auto l
= expr
->getLocStart();
383 while (compiler
.getSourceManager().isMacroArgExpansion(l
)) {
384 l
= compiler
.getSourceManager().getImmediateMacroCallerLoc(l
);
386 if (compiler
.getSourceManager().isMacroBodyExpansion(l
)) {
387 auto n
= Lexer::getImmediateMacroName(
388 l
, compiler
.getSourceManager(), compiler
.getLangOpts());
389 if (n
== "sal_False" || n
== "sal_True") {
393 auto e1
= expr
->getSubExprAsWritten();
394 auto t
= e1
->getType();
395 if (!t
->isFundamentalType() || loplugin::TypeCheck(t
).AnyBoolean()) {
398 auto e2
= dyn_cast
<ConditionalOperator
>(e1
);
400 auto ic1
= dyn_cast
<ImplicitCastExpr
>(
401 e2
->getTrueExpr()->IgnoreParens());
402 auto ic2
= dyn_cast
<ImplicitCastExpr
>(
403 e2
->getFalseExpr()->IgnoreParens());
404 if (ic1
!= nullptr && ic2
!= nullptr
405 && ic1
->getType()->isSpecificBuiltinType(BuiltinType::Int
)
406 && (loplugin::TypeCheck(ic1
->getSubExprAsWritten()->getType())
408 && ic2
->getType()->isSpecificBuiltinType(BuiltinType::Int
)
409 && (loplugin::TypeCheck(ic2
->getSubExprAsWritten()->getType())
416 DiagnosticsEngine::Warning
, "conversion from %0 to sal_Bool",
418 << t
<< expr
->getSourceRange();
422 bool SalBool::VisitReturnStmt(ReturnStmt
const * stmt
) {
423 // Just enough to avoid warnings in rtl_getUriCharClass (sal/rtl/uri.cxx),
426 // static sal_Bool const aCharClass[][nCharClassSize] = ...;
430 // return aCharClass[eCharClass];
432 if (ignoreLocation(stmt
)) {
435 auto e
= stmt
->getRetValue();
439 auto t
= e
->getType();
440 if (!t
->isPointerType()) {
444 auto t2
= t
->getAs
<PointerType
>();
448 t
= t2
->getPointeeType();
453 auto e2
= dyn_cast
<ArraySubscriptExpr
>(e
->IgnoreParenImpCasts());
457 auto e3
= dyn_cast
<DeclRefExpr
>(e2
->getBase()->IgnoreParenImpCasts());
461 auto d
= dyn_cast
<VarDecl
>(e3
->getDecl());
469 bool SalBool::WalkUpFromParmVarDecl(ParmVarDecl
const * decl
) {
470 return VisitParmVarDecl(decl
);
473 bool SalBool::VisitParmVarDecl(ParmVarDecl
const * decl
) {
474 if (ignoreLocation(decl
)) {
477 if (isSalBool(decl
->getType().getNonReferenceType())) {
478 FunctionDecl
const * f
= dyn_cast
<FunctionDecl
>(decl
->getDeclContext());
479 if (f
!= nullptr) { // e.g.: typedef sal_Bool (* FuncPtr )( sal_Bool );
480 f
= f
->getCanonicalDecl();
481 if (!(hasCLanguageLinkageType(f
)
482 || (isInUnoIncludeFile(f
)
483 && (!f
->isInlined() || f
->hasAttr
<DeprecatedAttr
>()
484 || decl
->getType()->isReferenceType()
485 || hasBoolOverload(f
, false)))
486 || f
->isDeleted() || hasBoolOverload(f
, true)))
488 OverrideKind k
= getOverrideKind(f
);
489 if (k
!= OverrideKind::YES
) {
490 SourceLocation loc
{ decl
->getLocStart() };
491 TypeSourceInfo
* tsi
= decl
->getTypeSourceInfo();
492 if (tsi
!= nullptr) {
494 compiler
.getSourceManager().getExpansionLoc(
495 tsi
->getTypeLoc().getBeginLoc()) };
497 compiler
.getSourceManager().getExpansionLoc(
498 tsi
->getTypeLoc().getEndLoc()) };
499 assert(l
.isFileID() && end
.isFileID());
501 || (compiler
.getSourceManager()
502 .isBeforeInTranslationUnit(l
, end
)))
505 unsigned n
= Lexer::MeasureTokenLength(
506 l
, compiler
.getSourceManager(),
507 compiler
.getLangOpts());
509 compiler
.getSourceManager().getCharacterData(l
),
511 if (s
== "sal_Bool") {
518 l
= l
.getLocWithOffset(std::max
<unsigned>(n
, 1));
522 // Only rewrite declarations in include files if a
523 // definition is also seen, to avoid compilation of a
524 // definition (in a main file only processed later) to fail
525 // with a "mismatch" error before the rewriter had a chance
526 // to act upon the definition (but use the heuristic of
527 // assuming pure virtual functions do not have definitions);
528 // also, do not automatically rewrite functions that could
529 // implicitly override depend base functions (and thus stop
530 // doing so after the rewrite; note that this is less
531 // dangerous for return types than for parameter types,
532 // where the function would still implicitly override and
533 // cause a compilation error due to the incompatible return
535 if (!((compiler
.getSourceManager().isInMainFile(
536 compiler
.getSourceManager().getSpellingLoc(
537 dyn_cast
<FunctionDecl
>(
538 decl
->getDeclContext())
539 ->getNameInfo().getLoc()))
540 || f
->isDefined() || f
->isPure())
541 && k
!= OverrideKind::MAYBE
&& rewrite(loc
)))
544 DiagnosticsEngine::Warning
,
545 ("ParmVarDecl, use \"bool\" instead of"
548 << (k
== OverrideKind::MAYBE
549 ? (" (unless this member function overrides a"
550 " dependent base member function, even"
551 " though it is not marked 'override')")
553 << decl
->getSourceRange();
562 bool SalBool::WalkUpFromVarDecl(VarDecl
const * decl
) {
563 return VisitVarDecl(decl
);
566 bool SalBool::VisitVarDecl(VarDecl
const * decl
) {
567 if (ignoreLocation(decl
)) {
570 if (!decl
->isExternC()
571 && (isSalBool(decl
->getType()) || isSalBoolArray(decl
->getType()))
572 && !isInSpecialMainFile(
573 compiler
.getSourceManager().getSpellingLoc(decl
->getLocStart())))
575 varDecls_
.insert(decl
);
580 bool SalBool::WalkUpFromFieldDecl(FieldDecl
const * decl
) {
581 return VisitFieldDecl(decl
);
584 bool SalBool::VisitFieldDecl(FieldDecl
const * decl
) {
585 if (ignoreLocation(decl
)) {
588 if ((isSalBool(decl
->getType()) || isSalBoolArray(decl
->getType()))
589 && !isInSpecialMainFile(
590 compiler
.getSourceManager().getSpellingLoc(decl
->getLocStart())))
592 TagDecl
const * td
= dyn_cast
<TagDecl
>(decl
->getDeclContext());
593 assert(td
!= nullptr);
594 if (!(((td
->isStruct() || td
->isUnion()) && td
->isExternCContext())
595 || isInUnoIncludeFile(
596 compiler
.getSourceManager().getSpellingLoc(
597 decl
->getLocation()))))
599 SourceLocation loc
{ decl
->getLocStart() };
600 TypeSourceInfo
* tsi
= decl
->getTypeSourceInfo();
601 if (tsi
!= nullptr) {
603 compiler
.getSourceManager().getExpansionLoc(
604 tsi
->getTypeLoc().getBeginLoc()) };
606 compiler
.getSourceManager().getExpansionLoc(
607 tsi
->getTypeLoc().getEndLoc()) };
608 assert(l
.isFileID() && end
.isFileID());
610 || compiler
.getSourceManager().isBeforeInTranslationUnit(
614 unsigned n
= Lexer::MeasureTokenLength(
615 l
, compiler
.getSourceManager(),
616 compiler
.getLangOpts());
618 compiler
.getSourceManager().getCharacterData(l
),
620 if (s
== "sal_Bool") {
627 l
= l
.getLocWithOffset(std::max
<unsigned>(n
, 1));
633 DiagnosticsEngine::Warning
,
634 "FieldDecl, use \"bool\" instead of \"sal_Bool\"", loc
)
635 << decl
->getSourceRange();
642 bool SalBool::WalkUpFromFunctionDecl(FunctionDecl
const * decl
) {
643 return VisitFunctionDecl(decl
);
646 bool SalBool::VisitFunctionDecl(FunctionDecl
const * decl
) {
647 if (ignoreLocation(decl
)) {
650 if (isSalBool(compat::getReturnType(*decl
).getNonReferenceType())) {
651 FunctionDecl
const * f
= decl
->getCanonicalDecl();
652 OverrideKind k
= getOverrideKind(f
);
653 if (k
!= OverrideKind::YES
654 && !(hasCLanguageLinkageType(f
)
655 || (isInUnoIncludeFile(f
)
656 && (!f
->isInlined() || f
->hasAttr
<DeprecatedAttr
>()))))
658 SourceLocation loc
{ decl
->getLocStart() };
659 SourceLocation l
{ compiler
.getSourceManager().getExpansionLoc(
661 SourceLocation end
{ compiler
.getSourceManager().getExpansionLoc(
662 decl
->getNameInfo().getLoc()) };
663 assert(l
.isFileID() && end
.isFileID());
664 if (compiler
.getSourceManager().isBeforeInTranslationUnit(l
, end
)) {
666 unsigned n
= Lexer::MeasureTokenLength(
667 l
, compiler
.getSourceManager(), compiler
.getLangOpts());
669 compiler
.getSourceManager().getCharacterData(l
), n
};
670 if (s
== "sal_Bool") {
674 l
= l
.getLocWithOffset(std::max
<unsigned>(n
, 1));
677 // Only rewrite declarations in include files if a definition is
678 // also seen, to avoid compilation of a definition (in a main file
679 // only processed later) to fail with a "mismatch" error before the
680 // rewriter had a chance to act upon the definition (but use the
681 // heuristic of assuming pure virtual functions do not have
683 if (!((compiler
.getSourceManager().isInMainFile(
684 compiler
.getSourceManager().getSpellingLoc(
685 decl
->getNameInfo().getLoc()))
686 || f
->isDefined() || f
->isPure())
690 DiagnosticsEngine::Warning
,
691 "use \"bool\" instead of \"sal_Bool\" as return type%0",
693 << (k
== OverrideKind::MAYBE
694 ? (" (unless this member function overrides a dependent"
695 " base member function, even though it is not marked"
698 << decl
->getSourceRange();
705 bool SalBool::VisitValueDecl(ValueDecl
const * decl
) {
706 if (ignoreLocation(decl
)) {
709 if (isSalBool(decl
->getType()) && !rewrite(decl
->getLocStart())) {
711 DiagnosticsEngine::Warning
,
712 "ValueDecl, use \"bool\" instead of \"sal_Bool\"",
714 << decl
->getSourceRange();
719 bool SalBool::TraverseStaticAssertDecl(StaticAssertDecl
* decl
) {
720 // Ignore special code like
722 // static_cast<sal_Bool>(true) == sal_True
724 // inside static_assert in cppu/source/uno/check.cxx:
726 (compiler
.getSourceManager().getFilename(decl
->getLocation())
727 == SRCDIR
"/cppu/source/uno/check.cxx")
728 || RecursiveASTVisitor::TraverseStaticAssertDecl(decl
);
731 bool SalBool::TraverseLinkageSpecDecl(LinkageSpecDecl
* decl
) {
732 assert(externCContexts_
!= std::numeric_limits
<unsigned int>::max()); //TODO
734 bool ret
= RecursiveASTVisitor::TraverseLinkageSpecDecl(decl
);
735 assert(externCContexts_
!= 0);
740 bool SalBool::isFromCIncludeFile(SourceLocation spellingLocation
) const {
741 return !compiler
.getSourceManager().isInMainFile(spellingLocation
)
743 compiler
.getSourceManager().getPresumedLoc(spellingLocation
)
748 bool SalBool::isSharedCAndCppCode(SourceLocation location
) const {
749 // Assume that code is intended to be shared between C and C++ if it comes
750 // from an include file ending in .h, and is either in an extern "C" context
751 // or the body of a macro definition:
753 isFromCIncludeFile(compiler
.getSourceManager().getSpellingLoc(location
))
754 && (externCContexts_
!= 0
755 || compiler
.getSourceManager().isMacroBodyExpansion(location
));
758 bool SalBool::isInSpecialMainFile(SourceLocation spellingLocation
) const {
759 if (!compiler
.getSourceManager().isInMainFile(spellingLocation
)) {
762 auto f
= compiler
.getSourceManager().getFilename(spellingLocation
);
763 return f
== SRCDIR
"/cppu/qa/test_any.cxx"
764 || f
== SRCDIR
"/cppu/source/uno/check.cxx"; // TODO: the offset checks
767 bool SalBool::rewrite(SourceLocation location
) {
768 if (rewriter
!= nullptr) {
769 //TODO: "::sal_Bool" -> "bool", not "::bool"
770 SourceLocation loc
{ compiler
.getSourceManager().getExpansionLoc(
772 unsigned n
= Lexer::MeasureTokenLength(
773 loc
, compiler
.getSourceManager(), compiler
.getLangOpts());
774 if (std::string(compiler
.getSourceManager().getCharacterData(loc
), n
)
777 return replaceText(loc
, n
, "bool");
783 loplugin::Plugin::Registration
<SalBool
> X("salbool", true);
787 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */