2014-01-31 09:37:27 +01:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
|
|
/*
|
|
|
|
* This file is part of the LibreOffice project.
|
|
|
|
*
|
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef INCLUDED_COMPILERPLUGINS_CLANG_COMPAT_HXX
|
|
|
|
#define INCLUDED_COMPILERPLUGINS_CLANG_COMPAT_HXX
|
|
|
|
|
2014-02-25 10:15:28 +01:00
|
|
|
#include <memory>
|
|
|
|
#include <string>
|
|
|
|
|
2014-01-31 09:37:27 +01:00
|
|
|
#include "clang/AST/Decl.h"
|
2014-02-25 10:48:55 +01:00
|
|
|
#include "clang/AST/DeclBase.h"
|
|
|
|
#include "clang/AST/DeclCXX.h"
|
2014-02-21 23:59:04 +01:00
|
|
|
#include "clang/AST/Expr.h"
|
2014-01-31 09:37:27 +01:00
|
|
|
#include "clang/AST/Type.h"
|
2014-01-31 09:50:21 +01:00
|
|
|
#include "clang/Basic/Diagnostic.h"
|
|
|
|
#include "clang/Basic/DiagnosticIDs.h"
|
2014-04-15 16:53:51 +02:00
|
|
|
#include "clang/Basic/Linkage.h"
|
2014-04-02 17:53:43 +02:00
|
|
|
#include "clang/Basic/SourceManager.h"
|
2014-04-15 16:53:51 +02:00
|
|
|
#include "clang/Basic/Visibility.h"
|
2015-03-24 15:26:35 +02:00
|
|
|
#include "clang/Frontend/CompilerInstance.h"
|
2014-09-23 13:46:24 +02:00
|
|
|
#include "clang/Lex/PPCallbacks.h"
|
|
|
|
#include "clang/Lex/Preprocessor.h"
|
2014-01-31 09:50:21 +01:00
|
|
|
#include "llvm/ADT/StringRef.h"
|
2014-02-25 10:15:28 +01:00
|
|
|
#include "llvm/Support/FileSystem.h"
|
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2014-01-31 09:37:27 +01:00
|
|
|
|
2014-03-27 09:51:01 +01:00
|
|
|
#if (__clang_major__ == 3 && __clang_minor__ >= 4) || __clang_major__ > 3
|
|
|
|
#define LO_COMPILERPLUGINS_CLANG_COMPAT_HAVE_isAtEndOfImmediateMacroExpansion \
|
|
|
|
true
|
|
|
|
#else
|
|
|
|
#define LO_COMPILERPLUGINS_CLANG_COMPAT_HAVE_isAtEndOfImmediateMacroExpansion \
|
|
|
|
false
|
|
|
|
#endif
|
|
|
|
|
2014-01-31 10:31:30 +01:00
|
|
|
// Compatibility wrapper to abstract over (trivial) changes in the Clang API:
|
2014-01-31 09:37:27 +01:00
|
|
|
namespace compat {
|
|
|
|
|
2015-11-19 09:19:30 +01:00
|
|
|
inline bool isLookupContext(clang::DeclContext const & ctxt) {
|
2015-11-19 10:11:32 +01:00
|
|
|
#if (__clang_major__ == 3 && __clang_minor__ >= 7) || __clang_major__ > 3
|
2015-11-19 09:19:30 +01:00
|
|
|
return ctxt.isLookupContext();
|
|
|
|
#else
|
|
|
|
return !ctxt.isFunctionOrMethod()
|
|
|
|
&& ctxt.getDeclKind() != clang::Decl::LinkageSpec;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-02-25 10:48:55 +01:00
|
|
|
inline bool isExternCContext(clang::DeclContext const & ctxt) {
|
|
|
|
#if (__clang_major__ == 3 && __clang_minor__ >= 4) || __clang_major__ > 3
|
|
|
|
return ctxt.isExternCContext();
|
|
|
|
#else
|
|
|
|
for (clang::DeclContext const * c = &ctxt;
|
|
|
|
c->getDeclKind() != clang::Decl::TranslationUnit; c = c->getParent())
|
|
|
|
{
|
|
|
|
if (c->getDeclKind() == clang::Decl::LinkageSpec) {
|
|
|
|
return llvm::cast<clang::LinkageSpecDecl>(c)->getLanguage()
|
|
|
|
== clang::LinkageSpecDecl::lang_c;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2015-01-08 10:59:24 +01:00
|
|
|
inline bool isInExternCContext(clang::FunctionDecl const & decl) {
|
|
|
|
#if (__clang_major__ == 3 && __clang_minor__ >= 4) || __clang_major__ > 3
|
|
|
|
return decl.isInExternCContext();
|
|
|
|
#else
|
2015-01-08 12:37:05 +02:00
|
|
|
return isExternCContext(*decl.getCanonicalDecl()->getDeclContext());
|
2015-01-08 10:59:24 +01:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2015-08-04 09:36:32 +02:00
|
|
|
inline bool forallBases(
|
|
|
|
clang::CXXRecordDecl const & decl,
|
|
|
|
clang::CXXRecordDecl::ForallBasesCallback BaseMatches,
|
2015-08-04 10:25:48 +02:00
|
|
|
void* callbackParam,
|
2015-08-04 09:36:32 +02:00
|
|
|
bool AllowShortCircuit)
|
|
|
|
{
|
2015-09-20 19:37:48 -04:00
|
|
|
#if (__clang_major__ == 3 && __clang_minor__ > 7) || __clang_major__ > 3
|
2015-08-04 10:34:50 +02:00
|
|
|
(void) callbackParam;
|
2015-08-04 09:36:32 +02:00
|
|
|
return decl.forallBases(BaseMatches, AllowShortCircuit);
|
|
|
|
#else
|
2015-08-04 10:25:48 +02:00
|
|
|
return decl.forallBases(BaseMatches, callbackParam, AllowShortCircuit);
|
2015-08-04 09:36:32 +02:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-04-15 16:53:51 +02:00
|
|
|
#if (__clang_major__ == 3 && __clang_minor__ >= 3) || __clang_major__ > 3
|
|
|
|
typedef clang::LinkageInfo LinkageInfo;
|
|
|
|
#else
|
|
|
|
typedef clang::NamedDecl::LinkageInfo LinkageInfo;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
inline clang::Linkage getLinkage(LinkageInfo const & info) {
|
|
|
|
#if (__clang_major__ == 3 && __clang_minor__ >= 3) || __clang_major__ > 3
|
|
|
|
return info.getLinkage();
|
|
|
|
#else
|
|
|
|
return info.linkage();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
inline clang::Visibility getVisibility(LinkageInfo const & info) {
|
|
|
|
#if (__clang_major__ == 3 && __clang_minor__ >= 3) || __clang_major__ > 3
|
|
|
|
return info.getVisibility();
|
|
|
|
#else
|
|
|
|
return info.visibility();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-03-27 09:51:01 +01:00
|
|
|
inline bool isFirstDecl(clang::FunctionDecl const & decl) {
|
|
|
|
#if (__clang_major__ == 3 && __clang_minor__ >= 4) || __clang_major__ > 3
|
|
|
|
return decl.isFirstDecl();
|
|
|
|
#else
|
|
|
|
return decl.isFirstDeclaration();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-01-31 09:37:27 +01:00
|
|
|
inline clang::QualType getReturnType(clang::FunctionDecl const & decl) {
|
|
|
|
#if (__clang_major__ == 3 && __clang_minor__ >= 5) || __clang_major__ > 3
|
|
|
|
return decl.getReturnType();
|
|
|
|
#else
|
|
|
|
return decl.getResultType();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-03-14 11:59:07 +01:00
|
|
|
inline clang::QualType getReturnType(clang::FunctionProtoType const & type) {
|
|
|
|
#if (__clang_major__ == 3 && __clang_minor__ >= 5) || __clang_major__ > 3
|
|
|
|
return type.getReturnType();
|
|
|
|
#else
|
|
|
|
return type.getResultType();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-01-31 09:37:27 +01:00
|
|
|
inline unsigned getNumParams(clang::FunctionProtoType const & type) {
|
|
|
|
#if (__clang_major__ == 3 && __clang_minor__ >= 5) || __clang_major__ > 3
|
|
|
|
return type.getNumParams();
|
|
|
|
#else
|
|
|
|
return type.getNumArgs();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
inline clang::QualType getParamType(
|
|
|
|
clang::FunctionProtoType const & type, unsigned i)
|
|
|
|
{
|
|
|
|
#if (__clang_major__ == 3 && __clang_minor__ >= 5) || __clang_major__ > 3
|
|
|
|
return type.getParamType(i);
|
|
|
|
#else
|
|
|
|
return type.getArgType(i);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2015-08-04 09:36:32 +02:00
|
|
|
inline clang::Stmt::const_child_iterator begin(
|
|
|
|
clang::Stmt::const_child_range const & range)
|
|
|
|
{
|
2015-09-20 19:37:48 -04:00
|
|
|
#if (__clang_major__ == 3 && __clang_minor__ > 7) || __clang_major__ > 3
|
2015-08-04 09:36:32 +02:00
|
|
|
return range.begin();
|
|
|
|
#else
|
|
|
|
return range.first;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
inline clang::Stmt::const_child_iterator end(
|
|
|
|
clang::Stmt::const_child_range const & range)
|
|
|
|
{
|
2015-09-20 19:37:48 -04:00
|
|
|
#if (__clang_major__ == 3 && __clang_minor__ > 7) || __clang_major__ > 3
|
2015-08-04 09:36:32 +02:00
|
|
|
return range.end();
|
|
|
|
#else
|
|
|
|
return range.second;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-02-21 23:59:04 +01:00
|
|
|
inline unsigned getBuiltinCallee(clang::CallExpr const & expr) {
|
|
|
|
#if (__clang_major__ == 3 && __clang_minor__ >= 5) || __clang_major__ > 3
|
|
|
|
return expr.getBuiltinCallee();
|
|
|
|
#else
|
|
|
|
return expr.isBuiltinCall();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-04-02 17:53:43 +02:00
|
|
|
inline bool isInMainFile(
|
|
|
|
clang::SourceManager const & manager, clang::SourceLocation Loc)
|
|
|
|
{
|
|
|
|
#if (__clang_major__ == 3 && __clang_minor__ >= 4) || __clang_major__ > 3
|
|
|
|
return manager.isInMainFile(Loc);
|
|
|
|
#else
|
|
|
|
return manager.isFromMainFile(Loc);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-01-31 09:50:21 +01:00
|
|
|
inline unsigned getCustomDiagID(
|
2014-01-31 15:23:51 +00:00
|
|
|
clang::DiagnosticsEngine & engine, clang::DiagnosticsEngine::Level L,
|
2014-01-31 09:50:21 +01:00
|
|
|
llvm::StringRef FormatString)
|
|
|
|
{
|
|
|
|
#if (__clang_major__ == 3 && __clang_minor__ >= 5) || __clang_major__ > 3
|
|
|
|
return engine.getDiagnosticIDs()->getCustomDiagID(
|
|
|
|
static_cast<clang::DiagnosticIDs::Level>(L), FormatString);
|
|
|
|
#else
|
|
|
|
return engine.getCustomDiagID(L, FormatString);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-02-25 10:15:28 +01:00
|
|
|
inline std::unique_ptr<llvm::raw_fd_ostream> create_raw_fd_ostream(
|
|
|
|
char const * Filename, std::string & ErrorInfo)
|
|
|
|
{
|
2014-08-28 11:33:32 +02:00
|
|
|
#if (__clang_major__ == 3 && __clang_minor__ >= 6) || __clang_major__ > 3
|
|
|
|
std::error_code ec;
|
|
|
|
std::unique_ptr<llvm::raw_fd_ostream> s(
|
|
|
|
new llvm::raw_fd_ostream(Filename, ec, llvm::sys::fs::F_None));
|
|
|
|
ErrorInfo = ec ? "error: " + ec.message() : std::string();
|
|
|
|
return s;
|
|
|
|
#elif __clang_major__ == 3 && __clang_minor__ == 5
|
2014-02-25 10:15:28 +01:00
|
|
|
return std::unique_ptr<llvm::raw_fd_ostream>(
|
|
|
|
new llvm::raw_fd_ostream(Filename, ErrorInfo, llvm::sys::fs::F_None));
|
|
|
|
#else
|
|
|
|
return std::unique_ptr<llvm::raw_fd_ostream>(
|
|
|
|
new llvm::raw_fd_ostream(Filename, ErrorInfo));
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2015-02-26 17:21:37 +01:00
|
|
|
#if (__clang_major__ == 3 && __clang_minor__ >= 7) || __clang_major__ > 3
|
|
|
|
typedef clang::DeclContext::lookup_result DeclContextLookupResult;
|
|
|
|
typedef clang::DeclContext::lookup_iterator DeclContextLookupIterator;
|
|
|
|
#else
|
|
|
|
typedef clang::DeclContext::lookup_const_result DeclContextLookupResult;
|
|
|
|
typedef clang::DeclContext::lookup_const_iterator DeclContextLookupIterator;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
inline DeclContextLookupIterator begin(DeclContextLookupResult const & result) {
|
2014-07-02 19:19:17 +02:00
|
|
|
#if (__clang_major__ == 3 && __clang_minor__ >= 3) || __clang_major__ > 3
|
|
|
|
return result.begin();
|
|
|
|
#else
|
|
|
|
return result.first;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2015-02-26 17:21:37 +01:00
|
|
|
inline DeclContextLookupIterator end(DeclContextLookupResult const & result) {
|
2014-07-02 19:19:17 +02:00
|
|
|
#if (__clang_major__ == 3 && __clang_minor__ >= 3) || __clang_major__ > 3
|
|
|
|
return result.end();
|
|
|
|
#else
|
|
|
|
return result.second;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-09-23 13:46:24 +02:00
|
|
|
inline void addPPCallbacks(
|
|
|
|
clang::Preprocessor & preprocessor, clang::PPCallbacks * C)
|
|
|
|
{
|
|
|
|
#if (__clang_major__ == 3 && __clang_minor__ >= 6) || __clang_major__ > 3
|
|
|
|
preprocessor.addPPCallbacks(std::unique_ptr<clang::PPCallbacks>(C));
|
|
|
|
#else
|
|
|
|
preprocessor.addPPCallbacks(C);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2015-03-24 15:26:35 +02:00
|
|
|
inline bool isMacroBodyExpansion(clang::CompilerInstance& compiler, clang::SourceLocation location)
|
|
|
|
{
|
|
|
|
#if (__clang_major__ == 3 && __clang_minor__ >= 3) || __clang_major__ > 3
|
|
|
|
return compiler.getSourceManager().isMacroBodyExpansion(location);
|
|
|
|
#else
|
|
|
|
return location.isMacroID()
|
|
|
|
&& !compiler.getSourceManager().isMacroArgExpansion(location);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2015-11-06 14:23:56 +01:00
|
|
|
inline auto getAsTagDecl(clang::Type const& t) -> clang::TagDecl *
|
|
|
|
{
|
|
|
|
#if (__clang_major__ == 3 && __clang_minor__ > 5) || __clang_major__ > 3
|
|
|
|
// TODO not sure if it works with clang 3.6, trunk is known to work
|
|
|
|
return t.getAsTagDecl();
|
|
|
|
#else
|
|
|
|
return t.getAs<clang::TagType>()->getDecl();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2015-03-25 15:37:53 +02:00
|
|
|
}
|
|
|
|
|
2014-01-31 09:37:27 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|