зеркало из https://github.com/microsoft/clang.git
Merge commit '60ea58923cedab42181297ba150cab731449fc67' into HEAD
This commit is contained in:
Коммит
11db0fc320
|
@ -666,7 +666,7 @@ Adding additional style options
|
|||
===============================
|
||||
|
||||
Each additional style option adds costs to the clang-format project. Some of
|
||||
these costs affect the clang-format developement itself, as we need to make
|
||||
these costs affect the clang-format development itself, as we need to make
|
||||
sure that any given combination of options work and that new features don't
|
||||
break any of the existing options in any way. There are also costs for end users
|
||||
as options become less discoverable and people have to think about and make a
|
||||
|
|
|
@ -32,7 +32,7 @@ when compiling your code.
|
|||
|
||||
On the other hand, Clang/LLVM is natively a cross-compiler, meaning that
|
||||
one set of programs can compile to all targets by setting the ``-target``
|
||||
option. That makes it a lot easier for programers wishing to compile to
|
||||
option. That makes it a lot easier for programmers wishing to compile to
|
||||
different platforms and architectures, and for compiler developers that
|
||||
only have to maintain one build system, and for OS distributions, that
|
||||
need only one set of main packages.
|
||||
|
|
|
@ -1857,7 +1857,7 @@ in the `ARM C Language Extensions Release 2.0
|
|||
<http://infocenter.arm.com/help/topic/com.arm.doc.ihi0053c/IHI0053C_acle_2_0.pdf>`_.
|
||||
Note that these intrinsics are implemented as motion barriers that block
|
||||
reordering of memory accesses and side effect instructions. Other instructions
|
||||
like simple arithmatic may be reordered around the intrinsic. If you expect to
|
||||
like simple arithmetic may be reordered around the intrinsic. If you expect to
|
||||
have no reordering at all, use inline assembly instead.
|
||||
|
||||
X86/X86-64 Language Extensions
|
||||
|
|
|
@ -110,8 +110,8 @@ Sancov matches these files using module names and binaries file names.
|
|||
|
||||
Action (required)
|
||||
-print - Print coverage addresses
|
||||
-covered-functions - Print all covered funcions.
|
||||
-not-covered-functions - Print all not covered funcions.
|
||||
-covered-functions - Print all covered functions.
|
||||
-not-covered-functions - Print all not covered functions.
|
||||
-html-report - Print HTML coverage report.
|
||||
|
||||
Options
|
||||
|
|
|
@ -124,6 +124,7 @@ public:
|
|||
void mangleBlock(const DeclContext *DC, const BlockDecl *BD,
|
||||
raw_ostream &Out);
|
||||
|
||||
void mangleObjCMethodNameWithoutSize(const ObjCMethodDecl *MD, raw_ostream &);
|
||||
void mangleObjCMethodName(const ObjCMethodDecl *MD, raw_ostream &);
|
||||
|
||||
virtual void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &) = 0;
|
||||
|
|
|
@ -40,6 +40,7 @@ struct PrintingPolicy {
|
|||
SuppressUnwrittenScope(false), SuppressInitializers(false),
|
||||
ConstantArraySizeAsWritten(false), AnonymousTagLocations(true),
|
||||
SuppressStrongLifetime(false), SuppressLifetimeQualifiers(false),
|
||||
SuppressTemplateArgsInCXXConstructors(false),
|
||||
Bool(LO.Bool), TerseOutput(false), PolishForDeclaration(false),
|
||||
Half(LO.Half), MSWChar(LO.MicrosoftExt && !LO.WChar),
|
||||
IncludeNewlines(true), MSVCFormatting(false) { }
|
||||
|
@ -136,7 +137,11 @@ struct PrintingPolicy {
|
|||
/// \brief When true, suppress printing of lifetime qualifier in
|
||||
/// ARC.
|
||||
unsigned SuppressLifetimeQualifiers : 1;
|
||||
|
||||
|
||||
/// When true, suppresses printing template arguments in names of C++
|
||||
/// constructors.
|
||||
unsigned SuppressTemplateArgsInCXXConstructors : 1;
|
||||
|
||||
/// \brief Whether we can use 'bool' rather than '_Bool', even if the language
|
||||
/// doesn't actually have 'bool' (because, e.g., it is defined as a macro).
|
||||
unsigned Bool : 1;
|
||||
|
|
|
@ -3673,6 +3673,19 @@ AST_MATCHER(QualType, isAnyCharacter) {
|
|||
return Node->isAnyCharacterType();
|
||||
}
|
||||
|
||||
//// \brief Matches QualType nodes that are of any pointer type.
|
||||
///
|
||||
/// Given
|
||||
/// \code
|
||||
/// int *i = nullptr;
|
||||
/// int j;
|
||||
/// \endcode
|
||||
/// varDecl(hasType(isAnyPointer()))
|
||||
/// matches "int *i", but not "int j".
|
||||
AST_MATCHER(QualType, isAnyPointer) {
|
||||
return Node->isAnyPointerType();
|
||||
}
|
||||
|
||||
/// \brief Matches QualType nodes that are const-qualified, i.e., that
|
||||
/// include "top-level" const.
|
||||
///
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
//===- CodegenNameGenerator.h - Codegen name generation -------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Determines the name that the symbol will get for code generation.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_INDEX_CODEGENNAMEGENERATOR_H
|
||||
#define LLVM_CLANG_INDEX_CODEGENNAMEGENERATOR_H
|
||||
|
||||
#include "clang/Basic/LLVM.h"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace clang {
|
||||
class ASTContext;
|
||||
class Decl;
|
||||
|
||||
namespace index {
|
||||
|
||||
class CodegenNameGenerator {
|
||||
public:
|
||||
explicit CodegenNameGenerator(ASTContext &Ctx);
|
||||
~CodegenNameGenerator();
|
||||
|
||||
/// \returns true on failure to produce a name for the given decl, false on
|
||||
/// success.
|
||||
bool writeName(const Decl *D, raw_ostream &OS);
|
||||
|
||||
/// Version of \c writeName function that returns a string.
|
||||
std::string getName(const Decl *D);
|
||||
|
||||
/// This can return multiple mangled names when applicable, e.g. for C++
|
||||
/// constructors/destructors.
|
||||
std::vector<std::string> getAllManglings(const Decl *D);
|
||||
|
||||
private:
|
||||
struct Implementation;
|
||||
std::unique_ptr<Implementation> Impl;
|
||||
};
|
||||
|
||||
} // namespace index
|
||||
} // namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_INDEX_CODEGENNAMEGENERATOR_H
|
|
@ -13,6 +13,7 @@
|
|||
#include "clang/Index/IndexSymbol.h"
|
||||
|
||||
namespace clang {
|
||||
class ASTContext;
|
||||
class DeclContext;
|
||||
class Expr;
|
||||
class FileID;
|
||||
|
@ -33,6 +34,8 @@ public:
|
|||
|
||||
virtual ~IndexDataConsumer() {}
|
||||
|
||||
virtual void initialize(ASTContext &Ctx) {}
|
||||
|
||||
/// \returns true to continue indexing, or false to abort.
|
||||
virtual bool handleDeclOccurence(const Decl *D, SymbolRoleSet Roles,
|
||||
ArrayRef<SymbolRelation> Relations,
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
namespace clang {
|
||||
class Decl;
|
||||
class LangOptions;
|
||||
|
||||
namespace index {
|
||||
|
||||
|
@ -111,6 +112,10 @@ SymbolInfo getSymbolInfo(const Decl *D);
|
|||
void applyForEachSymbolRole(SymbolRoleSet Roles,
|
||||
llvm::function_ref<void(SymbolRole)> Fn);
|
||||
void printSymbolRoles(SymbolRoleSet Roles, raw_ostream &OS);
|
||||
|
||||
/// \returns true if no name was printed, false otherwise.
|
||||
bool printSymbolName(const Decl *D, const LangOptions &LO, raw_ostream &OS);
|
||||
|
||||
StringRef getSymbolKindString(SymbolKind K);
|
||||
StringRef getTemplateKindStr(SymbolCXXTemplateKind TK);
|
||||
StringRef getSymbolLanguageString(SymbolLanguage K);
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/DeclCXX.h"
|
||||
#include "clang/AST/DeclarationName.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/AST/TypeLoc.h"
|
||||
|
@ -140,6 +140,12 @@ static void printCXXConstructorDestructorName(QualType ClassType,
|
|||
OS << *ClassRec->getDecl();
|
||||
return;
|
||||
}
|
||||
if (Policy.SuppressTemplateArgsInCXXConstructors) {
|
||||
if (auto *InjTy = ClassType->getAs<InjectedClassNameType>()) {
|
||||
OS << *InjTy->getDecl();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!Policy.LangOpts.CPlusPlus) {
|
||||
// Passed policy is the default one from operator <<, use a C++ policy.
|
||||
LangOptions LO;
|
||||
|
|
|
@ -254,11 +254,8 @@ void MangleContext::mangleBlock(const DeclContext *DC, const BlockDecl *BD,
|
|||
mangleFunctionBlock(*this, Buffer, BD, Out);
|
||||
}
|
||||
|
||||
void MangleContext::mangleObjCMethodName(const ObjCMethodDecl *MD,
|
||||
raw_ostream &Out) {
|
||||
SmallString<64> Name;
|
||||
llvm::raw_svector_ostream OS(Name);
|
||||
|
||||
void MangleContext::mangleObjCMethodNameWithoutSize(const ObjCMethodDecl *MD,
|
||||
raw_ostream &OS) {
|
||||
const ObjCContainerDecl *CD =
|
||||
dyn_cast<ObjCContainerDecl>(MD->getDeclContext());
|
||||
assert (CD && "Missing container decl in GetNameForMethod");
|
||||
|
@ -268,6 +265,13 @@ void MangleContext::mangleObjCMethodName(const ObjCMethodDecl *MD,
|
|||
OS << ' ';
|
||||
MD->getSelector().print(OS);
|
||||
OS << ']';
|
||||
|
||||
}
|
||||
|
||||
void MangleContext::mangleObjCMethodName(const ObjCMethodDecl *MD,
|
||||
raw_ostream &Out) {
|
||||
SmallString<64> Name;
|
||||
llvm::raw_svector_ostream OS(Name);
|
||||
|
||||
mangleObjCMethodNameWithoutSize(MD, OS);
|
||||
Out << OS.str().size() << OS.str();
|
||||
}
|
||||
|
|
|
@ -264,6 +264,8 @@ RegistryMaps::RegistryMaps() {
|
|||
REGISTER_MATCHER(innerType);
|
||||
REGISTER_MATCHER(integerLiteral);
|
||||
REGISTER_MATCHER(isAnonymous);
|
||||
REGISTER_MATCHER(isAnyCharacter);
|
||||
REGISTER_MATCHER(isAnyPointer);
|
||||
REGISTER_MATCHER(isArrow);
|
||||
REGISTER_MATCHER(isBaseInitializer);
|
||||
REGISTER_MATCHER(isCatchAll);
|
||||
|
|
|
@ -376,14 +376,23 @@ bool CodeGenFunction::EmitOMPFirstprivateClause(const OMPExecutableDirective &D,
|
|||
OMPPrivateScope &PrivateScope) {
|
||||
if (!HaveInsertPoint())
|
||||
return false;
|
||||
bool FirstprivateIsLastprivate = false;
|
||||
llvm::DenseSet<const VarDecl *> Lastprivates;
|
||||
for (const auto *C : D.getClausesOfKind<OMPLastprivateClause>()) {
|
||||
for (const auto *D : C->varlists())
|
||||
Lastprivates.insert(
|
||||
cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl())->getCanonicalDecl());
|
||||
}
|
||||
llvm::DenseSet<const VarDecl *> EmittedAsFirstprivate;
|
||||
for (const auto *C : D.getClausesOfKind<OMPFirstprivateClause>()) {
|
||||
auto IRef = C->varlist_begin();
|
||||
auto InitsRef = C->inits().begin();
|
||||
for (auto IInit : C->private_copies()) {
|
||||
auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
|
||||
if (EmittedAsFirstprivate.count(OrigVD) == 0) {
|
||||
EmittedAsFirstprivate.insert(OrigVD);
|
||||
FirstprivateIsLastprivate =
|
||||
FirstprivateIsLastprivate ||
|
||||
(Lastprivates.count(OrigVD->getCanonicalDecl()) > 0);
|
||||
if (EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl()).second) {
|
||||
auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
|
||||
auto *VDInit = cast<VarDecl>(cast<DeclRefExpr>(*InitsRef)->getDecl());
|
||||
bool IsRegistered;
|
||||
|
@ -443,7 +452,7 @@ bool CodeGenFunction::EmitOMPFirstprivateClause(const OMPExecutableDirective &D,
|
|||
++IRef, ++InitsRef;
|
||||
}
|
||||
}
|
||||
return !EmittedAsFirstprivate.empty();
|
||||
return FirstprivateIsLastprivate && !EmittedAsFirstprivate.empty();
|
||||
}
|
||||
|
||||
void CodeGenFunction::EmitOMPPrivateClause(
|
||||
|
@ -490,7 +499,6 @@ bool CodeGenFunction::EmitOMPCopyinClause(const OMPExecutableDirective &D) {
|
|||
auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
|
||||
QualType Type = VD->getType();
|
||||
if (CopiedVars.insert(VD->getCanonicalDecl()).second) {
|
||||
|
||||
// Get the address of the master variable. If we are emitting code with
|
||||
// TLS support, the address is passed from the master as field in the
|
||||
// captured declaration.
|
||||
|
@ -964,12 +972,11 @@ void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) {
|
|||
auto &&CodeGen = [&S](CodeGenFunction &CGF) {
|
||||
OMPPrivateScope PrivateScope(CGF);
|
||||
bool Copyins = CGF.EmitOMPCopyinClause(S);
|
||||
bool Firstprivates = CGF.EmitOMPFirstprivateClause(S, PrivateScope);
|
||||
if (Copyins || Firstprivates) {
|
||||
(void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
|
||||
if (Copyins) {
|
||||
// Emit implicit barrier to synchronize threads and avoid data races on
|
||||
// initialization of firstprivate variables or propagation master's thread
|
||||
// values of threadprivate variables to local instances of that variables
|
||||
// of all other implicit threads.
|
||||
// propagation master's thread values of threadprivate variables to local
|
||||
// instances of that variables of all other implicit threads.
|
||||
CGF.CGM.getOpenMPRuntime().emitBarrierCall(
|
||||
CGF, S.getLocStart(), OMPD_unknown, /*EmitChecks=*/false,
|
||||
/*ForceSimpleCall=*/true);
|
||||
|
@ -1605,7 +1612,8 @@ bool CodeGenFunction::EmitOMPWorksharingLoop(const OMPLoopDirective &S) {
|
|||
OMPPrivateScope LoopScope(*this);
|
||||
if (EmitOMPFirstprivateClause(S, LoopScope)) {
|
||||
// Emit implicit barrier to synchronize threads and avoid data races on
|
||||
// initialization of firstprivate variables.
|
||||
// initialization of firstprivate variables and post-update of
|
||||
// lastprivate variables.
|
||||
CGM.getOpenMPRuntime().emitBarrierCall(
|
||||
*this, S.getLocStart(), OMPD_unknown, /*EmitChecks=*/false,
|
||||
/*ForceSimpleCall=*/true);
|
||||
|
@ -1804,7 +1812,8 @@ CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
|
|||
CodeGenFunction::OMPPrivateScope LoopScope(CGF);
|
||||
if (CGF.EmitOMPFirstprivateClause(S, LoopScope)) {
|
||||
// Emit implicit barrier to synchronize threads and avoid data races on
|
||||
// initialization of firstprivate variables.
|
||||
// initialization of firstprivate variables and post-update of lastprivate
|
||||
// variables.
|
||||
CGF.CGM.getOpenMPRuntime().emitBarrierCall(
|
||||
CGF, S.getLocStart(), OMPD_unknown, /*EmitChecks=*/false,
|
||||
/*ForceSimpleCall=*/true);
|
||||
|
@ -1883,8 +1892,7 @@ void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &S) {
|
|||
llvm::SmallVector<const Expr *, 8> SrcExprs;
|
||||
llvm::SmallVector<const Expr *, 8> AssignmentOps;
|
||||
// Check if there are any 'copyprivate' clauses associated with this
|
||||
// 'single'
|
||||
// construct.
|
||||
// 'single' construct.
|
||||
// Build a list of copyprivate variables along with helper expressions
|
||||
// (<source>, <destination>, <destination>=<source> expressions)
|
||||
for (const auto *C : S.getClausesOfKind<OMPCopyprivateClause>()) {
|
||||
|
@ -1897,10 +1905,9 @@ void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &S) {
|
|||
}
|
||||
LexicalScope Scope(*this, S.getSourceRange());
|
||||
// Emit code for 'single' region along with 'copyprivate' clauses
|
||||
bool HasFirstprivates;
|
||||
auto &&CodeGen = [&S, &HasFirstprivates](CodeGenFunction &CGF) {
|
||||
auto &&CodeGen = [&S](CodeGenFunction &CGF) {
|
||||
CodeGenFunction::OMPPrivateScope SingleScope(CGF);
|
||||
HasFirstprivates = CGF.EmitOMPFirstprivateClause(S, SingleScope);
|
||||
(void)CGF.EmitOMPFirstprivateClause(S, SingleScope);
|
||||
CGF.EmitOMPPrivateClause(S, SingleScope);
|
||||
(void)SingleScope.Privatize();
|
||||
|
||||
|
@ -1909,10 +1916,9 @@ void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &S) {
|
|||
CGM.getOpenMPRuntime().emitSingleRegion(*this, CodeGen, S.getLocStart(),
|
||||
CopyprivateVars, DestExprs, SrcExprs,
|
||||
AssignmentOps);
|
||||
// Emit an implicit barrier at the end (to avoid data race on firstprivate
|
||||
// init or if no 'nowait' clause was specified and no 'copyprivate' clause).
|
||||
if ((!S.getSingleClause<OMPNowaitClause>() || HasFirstprivates) &&
|
||||
CopyprivateVars.empty()) {
|
||||
// Emit an implicit barrier at the end (to avoid data race if no 'nowait'
|
||||
// clause was specified and no 'copyprivate' clause).
|
||||
if (!S.getSingleClause<OMPNowaitClause>() && CopyprivateVars.empty()) {
|
||||
CGM.getOpenMPRuntime().emitBarrierCall(
|
||||
*this, S.getLocStart(),
|
||||
S.getSingleClause<OMPNowaitClause>() ? OMPD_unknown : OMPD_single);
|
||||
|
|
|
@ -3128,6 +3128,22 @@ void FreeBSD::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
|
|||
}
|
||||
}
|
||||
|
||||
void FreeBSD::AddCXXStdlibLibArgs(const ArgList &Args,
|
||||
ArgStringList &CmdArgs) const {
|
||||
CXXStdlibType Type = GetCXXStdlibType(Args);
|
||||
bool Profiling = Args.hasArg(options::OPT_pg);
|
||||
|
||||
switch (Type) {
|
||||
case ToolChain::CST_Libcxx:
|
||||
CmdArgs.push_back(Profiling ? "-lc++_p" : "-lc++");
|
||||
break;
|
||||
|
||||
case ToolChain::CST_Libstdcxx:
|
||||
CmdArgs.push_back(Profiling ? "-lstdc++_p" : "-lstdc++");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Tool *FreeBSD::buildAssembler() const {
|
||||
return new tools::freebsd::Assembler(*this);
|
||||
}
|
||||
|
|
|
@ -728,6 +728,8 @@ public:
|
|||
void AddClangCXXStdlibIncludeArgs(
|
||||
const llvm::opt::ArgList &DriverArgs,
|
||||
llvm::opt::ArgStringList &CC1Args) const override;
|
||||
void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
|
||||
llvm::opt::ArgStringList &CmdArgs) const override;
|
||||
|
||||
bool UseSjLjExceptions(const llvm::opt::ArgList &Args) const override;
|
||||
bool isPIEDefault() const override;
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
set(LLVM_LINK_COMPONENTS
|
||||
Core
|
||||
Support
|
||||
)
|
||||
|
||||
add_clang_library(clangIndex
|
||||
CodegenNameGenerator.cpp
|
||||
CommentToXML.cpp
|
||||
USRGeneration.cpp
|
||||
IndexBody.cpp
|
||||
IndexDecl.cpp
|
||||
IndexingAction.cpp
|
||||
IndexingContext.cpp
|
||||
IndexSymbol.cpp
|
||||
IndexTypeSourceInfo.cpp
|
||||
USRGeneration.cpp
|
||||
|
||||
ADDITIONAL_HEADERS
|
||||
IndexingContext.h
|
||||
|
|
|
@ -0,0 +1,197 @@
|
|||
//===- CodegenNameGenerator.cpp - Codegen name generation -----------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Determines the name that the symbol will get for code generation.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Index/CodegenNameGenerator.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/DeclCXX.h"
|
||||
#include "clang/AST/DeclObjC.h"
|
||||
#include "clang/AST/Mangle.h"
|
||||
#include "clang/AST/VTableBuilder.h"
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
#include "llvm/IR/Mangler.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
using namespace clang;
|
||||
using namespace clang::index;
|
||||
|
||||
struct CodegenNameGenerator::Implementation {
|
||||
std::unique_ptr<MangleContext> MC;
|
||||
llvm::DataLayout DL;
|
||||
|
||||
Implementation(ASTContext &Ctx)
|
||||
: MC(Ctx.createMangleContext()),
|
||||
DL(Ctx.getTargetInfo().getDataLayoutString()) {}
|
||||
|
||||
bool writeName(const Decl *D, raw_ostream &OS) {
|
||||
// First apply frontend mangling.
|
||||
SmallString<128> FrontendBuf;
|
||||
llvm::raw_svector_ostream FrontendBufOS(FrontendBuf);
|
||||
if (auto *FD = dyn_cast<FunctionDecl>(D)) {
|
||||
if (FD->isDependentContext())
|
||||
return true;
|
||||
if (writeFuncOrVarName(FD, FrontendBufOS))
|
||||
return true;
|
||||
} else if (auto *VD = dyn_cast<VarDecl>(D)) {
|
||||
if (writeFuncOrVarName(VD, FrontendBufOS))
|
||||
return true;
|
||||
} else if (auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
|
||||
MC->mangleObjCMethodNameWithoutSize(MD, OS);
|
||||
return false;
|
||||
} else if (auto *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
|
||||
writeObjCClassName(ID, FrontendBufOS);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Now apply backend mangling.
|
||||
llvm::Mangler::getNameWithPrefix(OS, FrontendBufOS.str(), DL);
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string getName(const Decl *D) {
|
||||
std::string Name;
|
||||
{
|
||||
llvm::raw_string_ostream OS(Name);
|
||||
writeName(D, OS);
|
||||
}
|
||||
return Name;
|
||||
}
|
||||
|
||||
std::vector<std::string> getAllManglings(const Decl *D) {
|
||||
if (!(isa<CXXRecordDecl>(D) || isa<CXXMethodDecl>(D)))
|
||||
return {};
|
||||
|
||||
const NamedDecl *ND = cast<NamedDecl>(D);
|
||||
|
||||
ASTContext &Ctx = ND->getASTContext();
|
||||
std::unique_ptr<MangleContext> M(Ctx.createMangleContext());
|
||||
std::unique_ptr<llvm::DataLayout> DL(
|
||||
new llvm::DataLayout(Ctx.getTargetInfo().getDataLayoutString()));
|
||||
|
||||
std::vector<std::string> Manglings;
|
||||
|
||||
auto hasDefaultCXXMethodCC = [](ASTContext &C, const CXXMethodDecl *MD) {
|
||||
auto DefaultCC = C.getDefaultCallingConvention(/*IsVariadic=*/false,
|
||||
/*IsCSSMethod=*/true);
|
||||
auto CC = MD->getType()->getAs<FunctionProtoType>()->getCallConv();
|
||||
return CC == DefaultCC;
|
||||
};
|
||||
|
||||
if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(ND)) {
|
||||
Manglings.emplace_back(getMangledStructor(CD, Ctor_Base));
|
||||
|
||||
if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily())
|
||||
if (!CD->getParent()->isAbstract())
|
||||
Manglings.emplace_back(getMangledStructor(CD, Ctor_Complete));
|
||||
|
||||
if (Ctx.getTargetInfo().getCXXABI().isMicrosoft())
|
||||
if (CD->hasAttr<DLLExportAttr>() && CD->isDefaultConstructor())
|
||||
if (!(hasDefaultCXXMethodCC(Ctx, CD) && CD->getNumParams() == 0))
|
||||
Manglings.emplace_back(getMangledStructor(CD, Ctor_DefaultClosure));
|
||||
} else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(ND)) {
|
||||
Manglings.emplace_back(getMangledStructor(DD, Dtor_Base));
|
||||
if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily()) {
|
||||
Manglings.emplace_back(getMangledStructor(DD, Dtor_Complete));
|
||||
if (DD->isVirtual())
|
||||
Manglings.emplace_back(getMangledStructor(DD, Dtor_Deleting));
|
||||
}
|
||||
} else if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(ND)) {
|
||||
Manglings.emplace_back(getName(ND));
|
||||
if (MD->isVirtual())
|
||||
if (const auto *TIV = Ctx.getVTableContext()->getThunkInfo(MD))
|
||||
for (const auto &T : *TIV)
|
||||
Manglings.emplace_back(getMangledThunk(MD, T));
|
||||
}
|
||||
|
||||
return Manglings;
|
||||
}
|
||||
|
||||
private:
|
||||
bool writeFuncOrVarName(const NamedDecl *D, raw_ostream &OS) {
|
||||
if (MC->shouldMangleDeclName(D)) {
|
||||
if (const auto *CtorD = dyn_cast<CXXConstructorDecl>(D))
|
||||
MC->mangleCXXCtor(CtorD, Ctor_Complete, OS);
|
||||
else if (const auto *DtorD = dyn_cast<CXXDestructorDecl>(D))
|
||||
MC->mangleCXXDtor(DtorD, Dtor_Complete, OS);
|
||||
else
|
||||
MC->mangleName(D, OS);
|
||||
return false;
|
||||
} else {
|
||||
IdentifierInfo *II = D->getIdentifier();
|
||||
if (!II)
|
||||
return true;
|
||||
OS << II->getName();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void writeObjCClassName(const ObjCInterfaceDecl *D, raw_ostream &OS) {
|
||||
OS << getClassSymbolPrefix();
|
||||
OS << D->getObjCRuntimeNameAsString();
|
||||
}
|
||||
|
||||
static StringRef getClassSymbolPrefix() {
|
||||
return "OBJC_CLASS_$_";
|
||||
}
|
||||
|
||||
std::string getMangledStructor(const NamedDecl *ND, unsigned StructorType) {
|
||||
std::string FrontendBuf;
|
||||
llvm::raw_string_ostream FOS(FrontendBuf);
|
||||
|
||||
if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(ND))
|
||||
MC->mangleCXXCtor(CD, static_cast<CXXCtorType>(StructorType), FOS);
|
||||
else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(ND))
|
||||
MC->mangleCXXDtor(DD, static_cast<CXXDtorType>(StructorType), FOS);
|
||||
|
||||
std::string BackendBuf;
|
||||
llvm::raw_string_ostream BOS(BackendBuf);
|
||||
|
||||
llvm::Mangler::getNameWithPrefix(BOS, FOS.str(), DL);
|
||||
|
||||
return BOS.str();
|
||||
}
|
||||
|
||||
std::string getMangledThunk(const CXXMethodDecl *MD, const ThunkInfo &T) {
|
||||
std::string FrontendBuf;
|
||||
llvm::raw_string_ostream FOS(FrontendBuf);
|
||||
|
||||
MC->mangleThunk(MD, T, FOS);
|
||||
|
||||
std::string BackendBuf;
|
||||
llvm::raw_string_ostream BOS(BackendBuf);
|
||||
|
||||
llvm::Mangler::getNameWithPrefix(BOS, FOS.str(), DL);
|
||||
|
||||
return BOS.str();
|
||||
}
|
||||
};
|
||||
|
||||
CodegenNameGenerator::CodegenNameGenerator(ASTContext &Ctx)
|
||||
: Impl(new Implementation(Ctx)) {
|
||||
}
|
||||
|
||||
CodegenNameGenerator::~CodegenNameGenerator() {
|
||||
}
|
||||
|
||||
bool CodegenNameGenerator::writeName(const Decl *D, raw_ostream &OS) {
|
||||
return Impl->writeName(D, OS);
|
||||
}
|
||||
|
||||
std::string CodegenNameGenerator::getName(const Decl *D) {
|
||||
return Impl->getName(D);
|
||||
}
|
||||
|
||||
std::vector<std::string> CodegenNameGenerator::getAllManglings(const Decl *D) {
|
||||
return Impl->getAllManglings(D);
|
||||
}
|
|
@ -11,6 +11,7 @@
|
|||
#include "clang/AST/DeclCXX.h"
|
||||
#include "clang/AST/DeclObjC.h"
|
||||
#include "clang/AST/DeclTemplate.h"
|
||||
#include "clang/AST/PrettyPrinter.h"
|
||||
|
||||
using namespace clang;
|
||||
using namespace clang::index;
|
||||
|
@ -234,6 +235,24 @@ void index::printSymbolRoles(SymbolRoleSet Roles, raw_ostream &OS) {
|
|||
});
|
||||
}
|
||||
|
||||
bool index::printSymbolName(const Decl *D, const LangOptions &LO,
|
||||
raw_ostream &OS) {
|
||||
if (auto *ND = dyn_cast<NamedDecl>(D)) {
|
||||
PrintingPolicy Policy(LO);
|
||||
// Forward references can have different template argument names. Suppress
|
||||
// the template argument names in constructors to make their name more
|
||||
// stable.
|
||||
Policy.SuppressTemplateArgsInCXXConstructors = true;
|
||||
DeclarationName DeclName = ND->getDeclName();
|
||||
if (DeclName.isEmpty())
|
||||
return true;
|
||||
DeclName.print(OS, Policy);
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
StringRef index::getSymbolKindString(SymbolKind K) {
|
||||
switch (K) {
|
||||
case SymbolKind::Unknown: return "<unknown>";
|
||||
|
@ -266,6 +285,7 @@ StringRef index::getSymbolKindString(SymbolKind K) {
|
|||
case SymbolKind::CXXTypeAlias: return "type-alias";
|
||||
case SymbolKind::CXXInterface: return "c++-__interface";
|
||||
}
|
||||
llvm_unreachable("invalid symbol kind");
|
||||
}
|
||||
|
||||
StringRef index::getTemplateKindStr(SymbolCXXTemplateKind TK) {
|
||||
|
@ -275,6 +295,7 @@ StringRef index::getTemplateKindStr(SymbolCXXTemplateKind TK) {
|
|||
case SymbolCXXTemplateKind::TemplatePartialSpecialization : return "TPS";
|
||||
case SymbolCXXTemplateKind::TemplateSpecialization: return "TS";
|
||||
}
|
||||
llvm_unreachable("invalid template kind");
|
||||
}
|
||||
|
||||
StringRef index::getSymbolLanguageString(SymbolLanguage K) {
|
||||
|
@ -283,4 +304,5 @@ StringRef index::getSymbolLanguageString(SymbolLanguage K) {
|
|||
case SymbolLanguage::ObjC: return "ObjC";
|
||||
case SymbolLanguage::CXX: return "C++";
|
||||
}
|
||||
llvm_unreachable("invalid symbol language kind");
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ public:
|
|||
protected:
|
||||
void Initialize(ASTContext &Context) override {
|
||||
IndexCtx.setASTContext(Context);
|
||||
IndexCtx.getDataConsumer().initialize(Context);
|
||||
}
|
||||
|
||||
bool HandleTopLevelDecl(DeclGroupRef DG) override {
|
||||
|
@ -170,5 +171,6 @@ void index::indexASTUnit(ASTUnit &Unit,
|
|||
IndexingOptions Opts) {
|
||||
IndexingContext IndexCtx(Opts, *DataConsumer);
|
||||
IndexCtx.setASTContext(Unit.getASTContext());
|
||||
DataConsumer->initialize(Unit.getASTContext());
|
||||
indexTranslationUnit(Unit, IndexCtx);
|
||||
}
|
||||
|
|
|
@ -135,6 +135,7 @@ bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) {
|
|||
case TSK_ExplicitInstantiationDefinition:
|
||||
return true;
|
||||
}
|
||||
llvm_unreachable("invalid TemplateSpecializationKind");
|
||||
}
|
||||
|
||||
bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) {
|
||||
|
|
|
@ -210,7 +210,12 @@ void USRGenerator::VisitFunctionDecl(const FunctionDecl *D) {
|
|||
VisitTemplateParameterList(FunTmpl->getTemplateParameters());
|
||||
} else
|
||||
Out << "@F@";
|
||||
D->printName(Out);
|
||||
|
||||
PrintingPolicy Policy(Context->getLangOpts());
|
||||
// Forward references can have different template argument names. Suppress the
|
||||
// template argument names in constructors to make their USR more stable.
|
||||
Policy.SuppressTemplateArgsInCXXConstructors = true;
|
||||
D->getDeclName().print(Out, Policy);
|
||||
|
||||
ASTContext &Ctx = *Context;
|
||||
if (!Ctx.getLangOpts().CPlusPlus || D->isExternC())
|
||||
|
|
|
@ -5818,10 +5818,12 @@ void Sema::CheckStrncatArguments(const CallExpr *CE,
|
|||
|
||||
//===--- CHECK: Return Address of Stack Variable --------------------------===//
|
||||
|
||||
static Expr *EvalVal(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars,
|
||||
Decl *ParentDecl);
|
||||
static Expr *EvalAddr(Expr* E, SmallVectorImpl<DeclRefExpr *> &refVars,
|
||||
Decl *ParentDecl);
|
||||
static const Expr *EvalVal(const Expr *E,
|
||||
SmallVectorImpl<const DeclRefExpr *> &refVars,
|
||||
const Decl *ParentDecl);
|
||||
static const Expr *EvalAddr(const Expr *E,
|
||||
SmallVectorImpl<const DeclRefExpr *> &refVars,
|
||||
const Decl *ParentDecl);
|
||||
|
||||
/// CheckReturnStackAddr - Check if a return statement returns the address
|
||||
/// of a stack variable.
|
||||
|
@ -5829,8 +5831,8 @@ static void
|
|||
CheckReturnStackAddr(Sema &S, Expr *RetValExp, QualType lhsType,
|
||||
SourceLocation ReturnLoc) {
|
||||
|
||||
Expr *stackE = nullptr;
|
||||
SmallVector<DeclRefExpr *, 8> refVars;
|
||||
const Expr *stackE = nullptr;
|
||||
SmallVector<const DeclRefExpr *, 8> refVars;
|
||||
|
||||
// Perform checking for returned stack addresses, local blocks,
|
||||
// label addresses or references to temporaries.
|
||||
|
@ -5858,7 +5860,8 @@ CheckReturnStackAddr(Sema &S, Expr *RetValExp, QualType lhsType,
|
|||
diagRange = refVars[0]->getSourceRange();
|
||||
}
|
||||
|
||||
if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(stackE)) { //address of local var.
|
||||
if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(stackE)) {
|
||||
// address of local var
|
||||
S.Diag(diagLoc, diag::warn_ret_stack_addr_ref) << lhsType->isReferenceType()
|
||||
<< DR->getDecl()->getDeclName() << diagRange;
|
||||
} else if (isa<BlockExpr>(stackE)) { // local block.
|
||||
|
@ -5873,12 +5876,12 @@ CheckReturnStackAddr(Sema &S, Expr *RetValExp, QualType lhsType,
|
|||
// Display the "trail" of reference variables that we followed until we
|
||||
// found the problematic expression using notes.
|
||||
for (unsigned i = 0, e = refVars.size(); i != e; ++i) {
|
||||
VarDecl *VD = cast<VarDecl>(refVars[i]->getDecl());
|
||||
const VarDecl *VD = cast<VarDecl>(refVars[i]->getDecl());
|
||||
// If this var binds to another reference var, show the range of the next
|
||||
// var, otherwise the var binds to the problematic expression, in which case
|
||||
// show the range of the expression.
|
||||
SourceRange range = (i < e-1) ? refVars[i+1]->getSourceRange()
|
||||
: stackE->getSourceRange();
|
||||
SourceRange range = (i < e - 1) ? refVars[i + 1]->getSourceRange()
|
||||
: stackE->getSourceRange();
|
||||
S.Diag(VD->getLocation(), diag::note_ref_var_local_bind)
|
||||
<< VD->getDeclName() << range;
|
||||
}
|
||||
|
@ -5910,8 +5913,9 @@ CheckReturnStackAddr(Sema &S, Expr *RetValExp, QualType lhsType,
|
|||
/// * arbitrary interplay between "&" and "*" operators
|
||||
/// * pointer arithmetic from an address of a stack variable
|
||||
/// * taking the address of an array element where the array is on the stack
|
||||
static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars,
|
||||
Decl *ParentDecl) {
|
||||
static const Expr *EvalAddr(const Expr *E,
|
||||
SmallVectorImpl<const DeclRefExpr *> &refVars,
|
||||
const Decl *ParentDecl) {
|
||||
if (E->isTypeDependent())
|
||||
return nullptr;
|
||||
|
||||
|
@ -5928,13 +5932,13 @@ static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars,
|
|||
// EvalAddr and EvalVal appropriately.
|
||||
switch (E->getStmtClass()) {
|
||||
case Stmt::DeclRefExprClass: {
|
||||
DeclRefExpr *DR = cast<DeclRefExpr>(E);
|
||||
const DeclRefExpr *DR = cast<DeclRefExpr>(E);
|
||||
|
||||
// If we leave the immediate function, the lifetime isn't about to end.
|
||||
if (DR->refersToEnclosingVariableOrCapture())
|
||||
return nullptr;
|
||||
|
||||
if (VarDecl *V = dyn_cast<VarDecl>(DR->getDecl()))
|
||||
if (const VarDecl *V = dyn_cast<VarDecl>(DR->getDecl()))
|
||||
// If this is a reference variable, follow through to the expression that
|
||||
// it points to.
|
||||
if (V->hasLocalStorage() &&
|
||||
|
@ -5950,44 +5954,44 @@ static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars,
|
|||
case Stmt::UnaryOperatorClass: {
|
||||
// The only unary operator that make sense to handle here
|
||||
// is AddrOf. All others don't make sense as pointers.
|
||||
UnaryOperator *U = cast<UnaryOperator>(E);
|
||||
const UnaryOperator *U = cast<UnaryOperator>(E);
|
||||
|
||||
if (U->getOpcode() == UO_AddrOf)
|
||||
return EvalVal(U->getSubExpr(), refVars, ParentDecl);
|
||||
else
|
||||
return nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
case Stmt::BinaryOperatorClass: {
|
||||
// Handle pointer arithmetic. All other binary operators are not valid
|
||||
// in this context.
|
||||
BinaryOperator *B = cast<BinaryOperator>(E);
|
||||
const BinaryOperator *B = cast<BinaryOperator>(E);
|
||||
BinaryOperatorKind op = B->getOpcode();
|
||||
|
||||
if (op != BO_Add && op != BO_Sub)
|
||||
return nullptr;
|
||||
|
||||
Expr *Base = B->getLHS();
|
||||
const Expr *Base = B->getLHS();
|
||||
|
||||
// Determine which argument is the real pointer base. It could be
|
||||
// the RHS argument instead of the LHS.
|
||||
if (!Base->getType()->isPointerType()) Base = B->getRHS();
|
||||
if (!Base->getType()->isPointerType())
|
||||
Base = B->getRHS();
|
||||
|
||||
assert (Base->getType()->isPointerType());
|
||||
assert(Base->getType()->isPointerType());
|
||||
return EvalAddr(Base, refVars, ParentDecl);
|
||||
}
|
||||
|
||||
// For conditional operators we need to see if either the LHS or RHS are
|
||||
// valid DeclRefExpr*s. If one of them is valid, we return it.
|
||||
case Stmt::ConditionalOperatorClass: {
|
||||
ConditionalOperator *C = cast<ConditionalOperator>(E);
|
||||
const ConditionalOperator *C = cast<ConditionalOperator>(E);
|
||||
|
||||
// Handle the GNU extension for missing LHS.
|
||||
// FIXME: That isn't a ConditionalOperator, so doesn't get here.
|
||||
if (Expr *LHSExpr = C->getLHS()) {
|
||||
if (const Expr *LHSExpr = C->getLHS()) {
|
||||
// In C++, we can have a throw-expression, which has 'void' type.
|
||||
if (!LHSExpr->getType()->isVoidType())
|
||||
if (Expr *LHS = EvalAddr(LHSExpr, refVars, ParentDecl))
|
||||
if (const Expr *LHS = EvalAddr(LHSExpr, refVars, ParentDecl))
|
||||
return LHS;
|
||||
}
|
||||
|
||||
|
@ -6020,7 +6024,7 @@ static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars,
|
|||
case Stmt::CXXDynamicCastExprClass:
|
||||
case Stmt::CXXConstCastExprClass:
|
||||
case Stmt::CXXReinterpretCastExprClass: {
|
||||
Expr* SubExpr = cast<CastExpr>(E)->getSubExpr();
|
||||
const Expr* SubExpr = cast<CastExpr>(E)->getSubExpr();
|
||||
switch (cast<CastExpr>(E)->getCastKind()) {
|
||||
case CK_LValueToRValue:
|
||||
case CK_NoOp:
|
||||
|
@ -6050,13 +6054,12 @@ static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars,
|
|||
}
|
||||
|
||||
case Stmt::MaterializeTemporaryExprClass:
|
||||
if (Expr *Result = EvalAddr(
|
||||
cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr(),
|
||||
refVars, ParentDecl))
|
||||
if (const Expr *Result =
|
||||
EvalAddr(cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr(),
|
||||
refVars, ParentDecl))
|
||||
return Result;
|
||||
|
||||
return E;
|
||||
|
||||
|
||||
// Everything else: we simply don't reason about them.
|
||||
default:
|
||||
return nullptr;
|
||||
|
@ -6065,141 +6068,147 @@ static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars,
|
|||
|
||||
/// EvalVal - This function is complements EvalAddr in the mutual recursion.
|
||||
/// See the comments for EvalAddr for more details.
|
||||
static Expr *EvalVal(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars,
|
||||
Decl *ParentDecl) {
|
||||
do {
|
||||
// We should only be called for evaluating non-pointer expressions, or
|
||||
// expressions with a pointer type that are not used as references but instead
|
||||
// are l-values (e.g., DeclRefExpr with a pointer type).
|
||||
static const Expr *EvalVal(const Expr *E,
|
||||
SmallVectorImpl<const DeclRefExpr *> &refVars,
|
||||
const Decl *ParentDecl) {
|
||||
do {
|
||||
// We should only be called for evaluating non-pointer expressions, or
|
||||
// expressions with a pointer type that are not used as references but
|
||||
// instead
|
||||
// are l-values (e.g., DeclRefExpr with a pointer type).
|
||||
|
||||
// Our "symbolic interpreter" is just a dispatch off the currently
|
||||
// viewed AST node. We then recursively traverse the AST by calling
|
||||
// EvalAddr and EvalVal appropriately.
|
||||
// Our "symbolic interpreter" is just a dispatch off the currently
|
||||
// viewed AST node. We then recursively traverse the AST by calling
|
||||
// EvalAddr and EvalVal appropriately.
|
||||
|
||||
E = E->IgnoreParens();
|
||||
switch (E->getStmtClass()) {
|
||||
case Stmt::ImplicitCastExprClass: {
|
||||
ImplicitCastExpr *IE = cast<ImplicitCastExpr>(E);
|
||||
if (IE->getValueKind() == VK_LValue) {
|
||||
E = IE->getSubExpr();
|
||||
continue;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
case Stmt::ExprWithCleanupsClass:
|
||||
return EvalVal(cast<ExprWithCleanups>(E)->getSubExpr(), refVars,ParentDecl);
|
||||
|
||||
case Stmt::DeclRefExprClass: {
|
||||
// When we hit a DeclRefExpr we are looking at code that refers to a
|
||||
// variable's name. If it's not a reference variable we check if it has
|
||||
// local storage within the function, and if so, return the expression.
|
||||
DeclRefExpr *DR = cast<DeclRefExpr>(E);
|
||||
|
||||
// If we leave the immediate function, the lifetime isn't about to end.
|
||||
if (DR->refersToEnclosingVariableOrCapture())
|
||||
E = E->IgnoreParens();
|
||||
switch (E->getStmtClass()) {
|
||||
case Stmt::ImplicitCastExprClass: {
|
||||
const ImplicitCastExpr *IE = cast<ImplicitCastExpr>(E);
|
||||
if (IE->getValueKind() == VK_LValue) {
|
||||
E = IE->getSubExpr();
|
||||
continue;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (VarDecl *V = dyn_cast<VarDecl>(DR->getDecl())) {
|
||||
// Check if it refers to itself, e.g. "int& i = i;".
|
||||
if (V == ParentDecl)
|
||||
return DR;
|
||||
case Stmt::ExprWithCleanupsClass:
|
||||
return EvalVal(cast<ExprWithCleanups>(E)->getSubExpr(), refVars,
|
||||
ParentDecl);
|
||||
|
||||
if (V->hasLocalStorage()) {
|
||||
if (!V->getType()->isReferenceType())
|
||||
case Stmt::DeclRefExprClass: {
|
||||
// When we hit a DeclRefExpr we are looking at code that refers to a
|
||||
// variable's name. If it's not a reference variable we check if it has
|
||||
// local storage within the function, and if so, return the expression.
|
||||
const DeclRefExpr *DR = cast<DeclRefExpr>(E);
|
||||
|
||||
// If we leave the immediate function, the lifetime isn't about to end.
|
||||
if (DR->refersToEnclosingVariableOrCapture())
|
||||
return nullptr;
|
||||
|
||||
if (const VarDecl *V = dyn_cast<VarDecl>(DR->getDecl())) {
|
||||
// Check if it refers to itself, e.g. "int& i = i;".
|
||||
if (V == ParentDecl)
|
||||
return DR;
|
||||
|
||||
// Reference variable, follow through to the expression that
|
||||
// it points to.
|
||||
if (V->hasInit()) {
|
||||
// Add the reference variable to the "trail".
|
||||
refVars.push_back(DR);
|
||||
return EvalVal(V->getInit(), refVars, V);
|
||||
if (V->hasLocalStorage()) {
|
||||
if (!V->getType()->isReferenceType())
|
||||
return DR;
|
||||
|
||||
// Reference variable, follow through to the expression that
|
||||
// it points to.
|
||||
if (V->hasInit()) {
|
||||
// Add the reference variable to the "trail".
|
||||
refVars.push_back(DR);
|
||||
return EvalVal(V->getInit(), refVars, V);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
case Stmt::UnaryOperatorClass: {
|
||||
// The only unary operator that make sense to handle here
|
||||
// is Deref. All others don't resolve to a "name." This includes
|
||||
// handling all sorts of rvalues passed to a unary operator.
|
||||
const UnaryOperator *U = cast<UnaryOperator>(E);
|
||||
|
||||
case Stmt::UnaryOperatorClass: {
|
||||
// The only unary operator that make sense to handle here
|
||||
// is Deref. All others don't resolve to a "name." This includes
|
||||
// handling all sorts of rvalues passed to a unary operator.
|
||||
UnaryOperator *U = cast<UnaryOperator>(E);
|
||||
if (U->getOpcode() == UO_Deref)
|
||||
return EvalAddr(U->getSubExpr(), refVars, ParentDecl);
|
||||
|
||||
if (U->getOpcode() == UO_Deref)
|
||||
return EvalAddr(U->getSubExpr(), refVars, ParentDecl);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
case Stmt::ArraySubscriptExprClass: {
|
||||
// Array subscripts are potential references to data on the stack. We
|
||||
// retrieve the DeclRefExpr* for the array variable if it indeed
|
||||
// has local storage.
|
||||
const auto *ASE = cast<ArraySubscriptExpr>(E);
|
||||
if (ASE->isTypeDependent())
|
||||
return nullptr;
|
||||
return EvalAddr(ASE->getBase(), refVars, ParentDecl);
|
||||
}
|
||||
|
||||
case Stmt::ArraySubscriptExprClass: {
|
||||
// Array subscripts are potential references to data on the stack. We
|
||||
// retrieve the DeclRefExpr* for the array variable if it indeed
|
||||
// has local storage.
|
||||
return EvalAddr(cast<ArraySubscriptExpr>(E)->getBase(), refVars,ParentDecl);
|
||||
}
|
||||
case Stmt::OMPArraySectionExprClass: {
|
||||
return EvalAddr(cast<OMPArraySectionExpr>(E)->getBase(), refVars,
|
||||
ParentDecl);
|
||||
}
|
||||
|
||||
case Stmt::OMPArraySectionExprClass: {
|
||||
return EvalAddr(cast<OMPArraySectionExpr>(E)->getBase(), refVars,
|
||||
ParentDecl);
|
||||
}
|
||||
case Stmt::ConditionalOperatorClass: {
|
||||
// For conditional operators we need to see if either the LHS or RHS are
|
||||
// non-NULL Expr's. If one is non-NULL, we return it.
|
||||
const ConditionalOperator *C = cast<ConditionalOperator>(E);
|
||||
|
||||
case Stmt::ConditionalOperatorClass: {
|
||||
// For conditional operators we need to see if either the LHS or RHS are
|
||||
// non-NULL Expr's. If one is non-NULL, we return it.
|
||||
ConditionalOperator *C = cast<ConditionalOperator>(E);
|
||||
// Handle the GNU extension for missing LHS.
|
||||
if (const Expr *LHSExpr = C->getLHS()) {
|
||||
// In C++, we can have a throw-expression, which has 'void' type.
|
||||
if (!LHSExpr->getType()->isVoidType())
|
||||
if (const Expr *LHS = EvalVal(LHSExpr, refVars, ParentDecl))
|
||||
return LHS;
|
||||
}
|
||||
|
||||
// Handle the GNU extension for missing LHS.
|
||||
if (Expr *LHSExpr = C->getLHS()) {
|
||||
// In C++, we can have a throw-expression, which has 'void' type.
|
||||
if (!LHSExpr->getType()->isVoidType())
|
||||
if (Expr *LHS = EvalVal(LHSExpr, refVars, ParentDecl))
|
||||
return LHS;
|
||||
if (C->getRHS()->getType()->isVoidType())
|
||||
return nullptr;
|
||||
|
||||
return EvalVal(C->getRHS(), refVars, ParentDecl);
|
||||
}
|
||||
|
||||
// In C++, we can have a throw-expression, which has 'void' type.
|
||||
if (C->getRHS()->getType()->isVoidType())
|
||||
return nullptr;
|
||||
// Accesses to members are potential references to data on the stack.
|
||||
case Stmt::MemberExprClass: {
|
||||
const MemberExpr *M = cast<MemberExpr>(E);
|
||||
|
||||
return EvalVal(C->getRHS(), refVars, ParentDecl);
|
||||
}
|
||||
// Check for indirect access. We only want direct field accesses.
|
||||
if (M->isArrow())
|
||||
return nullptr;
|
||||
|
||||
// Accesses to members are potential references to data on the stack.
|
||||
case Stmt::MemberExprClass: {
|
||||
MemberExpr *M = cast<MemberExpr>(E);
|
||||
// Check whether the member type is itself a reference, in which case
|
||||
// we're not going to refer to the member, but to what the member refers
|
||||
// to.
|
||||
if (M->getMemberDecl()->getType()->isReferenceType())
|
||||
return nullptr;
|
||||
|
||||
// Check for indirect access. We only want direct field accesses.
|
||||
if (M->isArrow())
|
||||
return nullptr;
|
||||
return EvalVal(M->getBase(), refVars, ParentDecl);
|
||||
}
|
||||
|
||||
// Check whether the member type is itself a reference, in which case
|
||||
// we're not going to refer to the member, but to what the member refers to.
|
||||
if (M->getMemberDecl()->getType()->isReferenceType())
|
||||
return nullptr;
|
||||
|
||||
return EvalVal(M->getBase(), refVars, ParentDecl);
|
||||
}
|
||||
|
||||
case Stmt::MaterializeTemporaryExprClass:
|
||||
if (Expr *Result = EvalVal(
|
||||
cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr(),
|
||||
refVars, ParentDecl))
|
||||
return Result;
|
||||
|
||||
return E;
|
||||
|
||||
default:
|
||||
// Check that we don't return or take the address of a reference to a
|
||||
// temporary. This is only useful in C++.
|
||||
if (!E->isTypeDependent() && E->isRValue())
|
||||
case Stmt::MaterializeTemporaryExprClass:
|
||||
if (const Expr *Result =
|
||||
EvalVal(cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr(),
|
||||
refVars, ParentDecl))
|
||||
return Result;
|
||||
return E;
|
||||
|
||||
// Everything else: we simply don't reason about them.
|
||||
return nullptr;
|
||||
}
|
||||
} while (true);
|
||||
default:
|
||||
// Check that we don't return or take the address of a reference to a
|
||||
// temporary. This is only useful in C++.
|
||||
if (!E->isTypeDependent() && E->isRValue())
|
||||
return E;
|
||||
|
||||
// Everything else: we simply don't reason about them.
|
||||
return nullptr;
|
||||
}
|
||||
} while (true);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -2,5 +2,12 @@
|
|||
// RUN: | FileCheck --check-prefix=CHECK-TEN %s
|
||||
// RUN: %clangxx %s -### -o %t.o -target amd64-unknown-freebsd9.2 2>&1 \
|
||||
// RUN: | FileCheck --check-prefix=CHECK-NINE %s
|
||||
// CHECK-TEN: -lc++
|
||||
// CHECK-NINE: -lstdc++
|
||||
// CHECK-TEN: "-lc++" "-lm"
|
||||
// CHECK-NINE: "-lstdc++" "-lm"
|
||||
|
||||
// RUN: %clangxx %s -### -pg -o %t.o -target amd64-unknown-freebsd10.0 2>&1 \
|
||||
// RUN: | FileCheck --check-prefix=CHECK-PG-TEN %s
|
||||
// RUN: %clangxx %s -### -pg -o %t.o -target amd64-unknown-freebsd9.2 2>&1 \
|
||||
// RUN: | FileCheck --check-prefix=CHECK-PG-NINE %s
|
||||
// CHECK-PG-TEN: "-lc++_p" "-lm_p"
|
||||
// CHECK-PG-NINE: "-lstdc++_p" "-lm_p"
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
// RUN: c-index-test core -print-source-symbols -- %s -target x86_64-apple-macosx10.7 | FileCheck %s
|
||||
|
||||
template <typename TemplArg>
|
||||
class TemplCls {
|
||||
// CHECK: [[@LINE-1]]:7 | c++-class/C++ | TemplCls | c:@ST>1#T@TemplCls | <no-cgname> | Def | rel: 0
|
||||
TemplCls(int x);
|
||||
// CHECK: [[@LINE-1]]:3 | constructor/C++ | TemplCls | c:@ST>1#T@TemplCls@F@TemplCls#I# | <no-cgname> | Decl/RelChild | rel: 1
|
||||
// CHECK-NEXT: RelChild | TemplCls | c:@ST>1#T@TemplCls
|
||||
};
|
|
@ -1,8 +1,8 @@
|
|||
// RUN: c-index-test core -print-source-symbols -- %s | FileCheck %s
|
||||
// RUN: c-index-test core -print-source-symbols -- %s -target x86_64-apple-macosx10.7 | FileCheck %s
|
||||
|
||||
@interface Base
|
||||
// CHECK: [[@LINE-1]]:12 | objc-class/ObjC | Base | c:objc(cs)Base | Decl | rel: 0
|
||||
// CHECK: [[@LINE-1]]:12 | objc-class/ObjC | Base | c:objc(cs)Base | _OBJC_CLASS_$_Base | Decl | rel: 0
|
||||
-(void)meth;
|
||||
// CHECK: [[@LINE-1]]:1 | objc-instance-method/ObjC | meth | c:objc(cs)Base(im)meth | Decl/Dyn/RelChild | rel: 1
|
||||
// CHECK: [[@LINE-1]]:1 | objc-instance-method/ObjC | meth | c:objc(cs)Base(im)meth | -[Base meth] | Decl/Dyn/RelChild | rel: 1
|
||||
// CHECK-NEXT: RelChild | Base | c:objc(cs)Base
|
||||
@end
|
||||
|
|
|
@ -95,7 +95,7 @@ int main() {
|
|||
// LAMBDA: [[SIVAR2_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[SIVAR2_PRIVATE_ADDR_REF]]
|
||||
// LAMBDA: store i{{[0-9]+}} [[SIVAR2_VAL]], i{{[0-9]+}}* [[SIVAR2_PRIVATE_ADDR]]
|
||||
|
||||
// LAMBDA: call void @__kmpc_barrier(
|
||||
// LAMBDA-NOT: call void @__kmpc_barrier(
|
||||
g = 1;
|
||||
g1 = 1;
|
||||
sivar = 2;
|
||||
|
@ -158,7 +158,7 @@ int main() {
|
|||
// BLOCKS: [[SIVAR2_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[SIVAR_REF_ADDRR]]
|
||||
// BLOCKS: store i{{[0-9]+}} {{.+}}, i{{[0-9]+}}* [[SIVAR2_PRIVATE_ADDR]]
|
||||
|
||||
// BLOCKS: call void @__kmpc_barrier(
|
||||
// BLOCKS-NOT: call void @__kmpc_barrier(
|
||||
g = 1;
|
||||
g1 =1;
|
||||
sivar = 2;
|
||||
|
@ -246,7 +246,7 @@ int main() {
|
|||
// CHECK: store i{{[0-9]+}} [[SIVAR_VAL]], i{{[0-9]+}}* [[SIVAR_PRIV]]
|
||||
|
||||
// Synchronization for initialization.
|
||||
// CHECK: call void @__kmpc_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
|
||||
// CHECK-NOT: call void @__kmpc_barrier(
|
||||
|
||||
// CHECK: call void @__kmpc_for_static_init_4(
|
||||
// CHECK: call void @__kmpc_for_static_fini(
|
||||
|
@ -310,10 +310,8 @@ int main() {
|
|||
// CHECK: call {{.*}} [[S_INT_TY_COPY_CONSTR]]([[S_INT_TY]]* [[VAR_PRIV]], [[S_INT_TY]]* {{.*}} [[VAR_REF]], [[ST_TY]]* [[ST_TY_TEMP]])
|
||||
// CHECK: call {{.*}} [[ST_TY_DESTR]]([[ST_TY]]* [[ST_TY_TEMP]])
|
||||
|
||||
// Synchronization for initialization.
|
||||
// CHECK: [[GTID_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[GTID_ADDR_ADDR]]
|
||||
// CHECK: [[GTID:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[GTID_REF]]
|
||||
// CHECK: call void @__kmpc_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
|
||||
// No synchronization for initialization.
|
||||
// CHECK-NOT: call void @__kmpc_barrier(
|
||||
|
||||
// CHECK: call void @__kmpc_for_static_init_4(
|
||||
// CHECK: call void @__kmpc_for_static_fini(
|
||||
|
|
|
@ -31,7 +31,6 @@ struct S {
|
|||
// CHECK-DAG: [[S_FLOAT_TY:%.+]] = type { float }
|
||||
// CHECK-DAG: [[S_INT_TY:%.+]] = type { i{{[0-9]+}} }
|
||||
// CHECK-DAG: [[ST_TY:%.+]] = type { i{{[0-9]+}}, i{{[0-9]+}} }
|
||||
// CHECK-DAG: [[IMPLICIT_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 66, i32 0, i32 0, i8*
|
||||
|
||||
template <typename T>
|
||||
T tmain() {
|
||||
|
@ -70,7 +69,7 @@ int main() {
|
|||
// LAMBDA: store i{{[0-9]+}} [[G_VAL]], i{{[0-9]+}}* [[G_PRIVATE_ADDR]], align 128
|
||||
// LAMBDA: [[SIVAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[SIVAR_REF]]
|
||||
// LAMBDA: store i{{[0-9]+}} [[SIVAR_VAL]], i{{[0-9]+}}* [[SIVAR_PRIVATE_ADDR]]
|
||||
// LAMBDA: call {{.*}}void @__kmpc_barrier(
|
||||
// LAMBDA-NOT: call {{.*}}void @__kmpc_barrier(
|
||||
g = 1;
|
||||
sivar = 2;
|
||||
// LAMBDA: store i{{[0-9]+}} 1, i{{[0-9]+}}* [[G_PRIVATE_ADDR]],
|
||||
|
@ -115,7 +114,7 @@ int main() {
|
|||
// BLOCK: [[SIVAR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SIVAR_REF_ADDR]]
|
||||
// BLOCKS: [[SIVAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[SIVAR_REF]],
|
||||
// BLOCKS: store i{{[0-9]+}} [[SIVAR_VAL]], i{{[0-9]+}}* [[SIVAR_PRIVATE_ADDR]],
|
||||
// BLOCKS: call {{.*}}void @__kmpc_barrier(
|
||||
// BLOCKS-NOT: call {{.*}}void @__kmpc_barrier(
|
||||
g = 1;
|
||||
sivar = 2;
|
||||
// BLOCKS: store i{{[0-9]+}} 1, i{{[0-9]+}}* [[G_PRIVATE_ADDR]],
|
||||
|
@ -244,9 +243,7 @@ int main() {
|
|||
// CHECK: call {{.*}} [[ST_TY_DEFAULT_CONSTR]]([[ST_TY]]* [[ST_TY_TEMP:%.+]])
|
||||
// CHECK: call {{.*}} [[S_INT_TY_COPY_CONSTR]]([[S_INT_TY]]* [[VAR_PRIV]], [[S_INT_TY]]* {{.*}} [[VAR_REF]], [[ST_TY]]* [[ST_TY_TEMP]])
|
||||
// CHECK: call {{.*}} [[ST_TY_DESTR]]([[ST_TY]]* [[ST_TY_TEMP]])
|
||||
// CHECK: [[GTID_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[GTID_ADDR_ADDR]]
|
||||
// CHECK: [[GTID:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[GTID_REF]]
|
||||
// CHECK: call {{.*}}void @__kmpc_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
|
||||
// CHECK-NOT: call {{.*}}void @__kmpc_barrier(
|
||||
// CHECK-DAG: call {{.*}} [[S_INT_TY_DESTR]]([[S_INT_TY]]* [[VAR_PRIV]])
|
||||
// CHECK-DAG: call {{.*}} [[S_INT_TY_DESTR]]([[S_INT_TY]]*
|
||||
// CHECK: ret void
|
||||
|
|
|
@ -59,7 +59,6 @@ S<float> s_arr[] = {1, 2};
|
|||
// CHECK-DAG: [[VAR:@.+]] = global [[S_FLOAT_TY]] zeroinitializer,
|
||||
S<float> var(3);
|
||||
// CHECK-DAG: [[SIVAR:@.+]] = internal global i{{[0-9]+}} 0,
|
||||
// CHECK-DAG: [[IMPLICIT_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 66, i32 0, i32 0, i8*
|
||||
// CHECK-DAG: [[SECTIONS_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 194, i32 0, i32 0, i8*
|
||||
|
||||
// CHECK: call {{.*}} [[S_FLOAT_TY_DEF_CONSTR:@.+]]([[S_FLOAT_TY]]* [[TEST]])
|
||||
|
@ -94,7 +93,7 @@ int main() {
|
|||
// LAMBDA: [[SIVAR1_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[SIVAR1_REF]]
|
||||
// LAMBDA: store i{{[0-9]+}} [[SIVAR1_VAL]], i{{[0-9]+}}* [[SIVAR1_PRIVATE_ADDR]]
|
||||
|
||||
// LAMBDA: call void @__kmpc_barrier(
|
||||
// LAMBDA-NOT: call void @__kmpc_barrier(
|
||||
{
|
||||
g = 1;
|
||||
sivar = 10;
|
||||
|
@ -154,7 +153,7 @@ int main() {
|
|||
|
||||
// BLOCKS: [[SIVAR1_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[SIVAR1_REF]],
|
||||
// BLOCKS: store i{{[0-9]+}} [[SIVAR1_VAL]], i{{[0-9]+}}* [[SIVAR1_PRIVATE_ADDR]],
|
||||
// BLOCKS: call void @__kmpc_barrier(
|
||||
// BLOCKS-NOT: call void @__kmpc_barrier(
|
||||
{
|
||||
g = 1;
|
||||
sivar = 10;
|
||||
|
@ -242,7 +241,7 @@ int main() {
|
|||
// CHECK: [[SIVAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[SIVAR]],
|
||||
// CHECK: store i{{[0-9]+}} [[SIVAR_VAL]], i{{[0-9]+}}* [[SIVAR_PRIV]],
|
||||
|
||||
// CHECK: call void @__kmpc_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
|
||||
// CHECK-NOT: call void @__kmpc_barrier(
|
||||
// CHECK: call void @__kmpc_for_static_init_4(
|
||||
// CHECK: call void @__kmpc_for_static_fini(
|
||||
|
||||
|
@ -304,10 +303,8 @@ int main() {
|
|||
// CHECK: call {{.*}} [[S_INT_TY_COPY_CONSTR]]([[S_INT_TY]]* [[VAR_PRIV]], [[S_INT_TY]]* {{.*}} [[VAR_REF]], [[ST_TY]]* [[ST_TY_TEMP]])
|
||||
// CHECK: call {{.*}} [[ST_TY_DESTR]]([[ST_TY]]* [[ST_TY_TEMP]])
|
||||
|
||||
// Synchronization for initialization.
|
||||
// CHECK: [[GTID_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[GTID_ADDR_ADDR]]
|
||||
// CHECK: [[GTID:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[GTID_REF]]
|
||||
// CHECK: call void @__kmpc_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
|
||||
// No synchronization for initialization.
|
||||
// CHECK-NOT: call void @__kmpc_barrier(
|
||||
|
||||
// CHECK: call void @__kmpc_for_static_init_4(
|
||||
// CHECK: call void @__kmpc_for_static_fini(
|
||||
|
|
|
@ -57,7 +57,6 @@ int vec[] = {1, 2};
|
|||
S<float> s_arr[] = {1, 2};
|
||||
// CHECK-DAG: [[VAR:@.+]] = global [[S_FLOAT_TY]] zeroinitializer,
|
||||
S<float> var(3);
|
||||
// CHECK-DAG: [[IMPLICIT_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 66, i32 0, i32 0, i8*
|
||||
// CHECK-DAG: [[SINGLE_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 322, i32 0, i32 0, i8*
|
||||
|
||||
// CHECK: call {{.*}} [[S_FLOAT_TY_DEF_CONSTR:@.+]]([[S_FLOAT_TY]]* [[TEST]])
|
||||
|
@ -215,7 +214,7 @@ int main() {
|
|||
// CHECK-DAG: call {{.*}} [[S_FLOAT_TY_DESTR]]([[S_FLOAT_TY]]*
|
||||
// CHECK: call void @__kmpc_end_single(
|
||||
|
||||
// CHECK: call void @__kmpc_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
|
||||
// CHECK-NOT: call void @__kmpc_barrier(
|
||||
|
||||
// CHECK: = call {{.*}}i{{.+}} [[TMAIN_INT:@.+]]()
|
||||
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -std=c++11 %s
|
||||
// expected-no-diagnostics
|
||||
|
||||
namespace PR26599 {
|
||||
template <typename>
|
||||
struct S;
|
||||
|
||||
struct I {};
|
||||
|
||||
template <typename T>
|
||||
void *&non_pointer() {
|
||||
void *&r = S<T>()[I{}];
|
||||
return r;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void *&pointer() {
|
||||
void *&r = S<T>()[nullptr];
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
|
@ -22,6 +22,9 @@ if (LLVM_BUILD_STATIC)
|
|||
else()
|
||||
target_link_libraries(c-index-test
|
||||
libclang
|
||||
clangAST
|
||||
clangBasic
|
||||
clangFrontend
|
||||
clangIndex
|
||||
)
|
||||
endif()
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "clang/Index/IndexingAction.h"
|
||||
#include "clang/Index/IndexDataConsumer.h"
|
||||
#include "clang/Index/USRGeneration.h"
|
||||
#include "clang/Index/CodegenNameGenerator.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Signals.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
@ -60,11 +61,16 @@ namespace {
|
|||
|
||||
class PrintIndexDataConsumer : public IndexDataConsumer {
|
||||
raw_ostream &OS;
|
||||
std::unique_ptr<CodegenNameGenerator> CGNameGen;
|
||||
|
||||
public:
|
||||
PrintIndexDataConsumer(raw_ostream &OS) : OS(OS) {
|
||||
}
|
||||
|
||||
void initialize(ASTContext &Ctx) override {
|
||||
CGNameGen.reset(new CodegenNameGenerator(Ctx));
|
||||
}
|
||||
|
||||
bool handleDeclOccurence(const Decl *D, SymbolRoleSet Roles,
|
||||
ArrayRef<SymbolRelation> Relations,
|
||||
FileID FID, unsigned Offset,
|
||||
|
@ -82,6 +88,10 @@ public:
|
|||
printSymbolNameAndUSR(D, Ctx, OS);
|
||||
OS << " | ";
|
||||
|
||||
if (CGNameGen->writeName(D, OS))
|
||||
OS << "<no-cgname>";
|
||||
OS << " | ";
|
||||
|
||||
printSymbolRoles(Roles, OS);
|
||||
OS << " | ";
|
||||
|
||||
|
@ -123,9 +133,8 @@ static bool printSourceSymbols(ArrayRef<const char *> Args) {
|
|||
/*WrappedAction=*/nullptr);
|
||||
|
||||
auto PCHContainerOps = std::make_shared<PCHContainerOperations>();
|
||||
ASTUnit *Unit =
|
||||
ASTUnit::LoadFromCompilerInvocationAction(CInvok.get(), PCHContainerOps,
|
||||
Diags, IndexAction.get());
|
||||
std::unique_ptr<ASTUnit> Unit(ASTUnit::LoadFromCompilerInvocationAction(
|
||||
CInvok.get(), PCHContainerOps, Diags, IndexAction.get()));
|
||||
|
||||
if (!Unit)
|
||||
return true;
|
||||
|
@ -147,10 +156,7 @@ static void printSymbolInfo(SymbolInfo SymInfo, raw_ostream &OS) {
|
|||
|
||||
static void printSymbolNameAndUSR(const Decl *D, ASTContext &Ctx,
|
||||
raw_ostream &OS) {
|
||||
if (auto *ND = dyn_cast<NamedDecl>(D)) {
|
||||
PrintingPolicy PrintPolicy(Ctx.getLangOpts());
|
||||
ND->getDeclName().print(OS, PrintPolicy);
|
||||
} else {
|
||||
if (printSymbolName(D, Ctx.getLangOpts(), OS)) {
|
||||
OS << "<no-name>";
|
||||
}
|
||||
OS << " | ";
|
||||
|
|
|
@ -22,17 +22,15 @@
|
|||
#include "CXType.h"
|
||||
#include "CursorVisitor.h"
|
||||
#include "clang/AST/Attr.h"
|
||||
#include "clang/AST/Mangle.h"
|
||||
#include "clang/AST/StmtVisitor.h"
|
||||
#include "clang/AST/VTableBuilder.h"
|
||||
#include "clang/Basic/Diagnostic.h"
|
||||
#include "clang/Basic/DiagnosticCategories.h"
|
||||
#include "clang/Basic/DiagnosticIDs.h"
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
#include "clang/Basic/Version.h"
|
||||
#include "clang/Frontend/ASTUnit.h"
|
||||
#include "clang/Frontend/CompilerInstance.h"
|
||||
#include "clang/Frontend/FrontendDiagnostic.h"
|
||||
#include "clang/Index/CodegenNameGenerator.h"
|
||||
#include "clang/Index/CommentToXML.h"
|
||||
#include "clang/Lex/HeaderSearch.h"
|
||||
#include "clang/Lex/Lexer.h"
|
||||
|
@ -43,8 +41,6 @@
|
|||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/Config/llvm-config.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
#include "llvm/IR/Mangler.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/CrashRecoveryContext.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
|
@ -3976,59 +3972,6 @@ static SourceLocation getLocationFromExpr(const Expr *E) {
|
|||
return E->getLocStart();
|
||||
}
|
||||
|
||||
static std::string getMangledStructor(std::unique_ptr<MangleContext> &M,
|
||||
std::unique_ptr<llvm::DataLayout> &DL,
|
||||
const NamedDecl *ND,
|
||||
unsigned StructorType) {
|
||||
std::string FrontendBuf;
|
||||
llvm::raw_string_ostream FOS(FrontendBuf);
|
||||
|
||||
if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(ND))
|
||||
M->mangleCXXCtor(CD, static_cast<CXXCtorType>(StructorType), FOS);
|
||||
else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(ND))
|
||||
M->mangleCXXDtor(DD, static_cast<CXXDtorType>(StructorType), FOS);
|
||||
|
||||
std::string BackendBuf;
|
||||
llvm::raw_string_ostream BOS(BackendBuf);
|
||||
|
||||
llvm::Mangler::getNameWithPrefix(BOS, llvm::Twine(FOS.str()), *DL);
|
||||
|
||||
return BOS.str();
|
||||
}
|
||||
|
||||
static std::string getMangledName(std::unique_ptr<MangleContext> &M,
|
||||
std::unique_ptr<llvm::DataLayout> &DL,
|
||||
const NamedDecl *ND) {
|
||||
std::string FrontendBuf;
|
||||
llvm::raw_string_ostream FOS(FrontendBuf);
|
||||
|
||||
M->mangleName(ND, FOS);
|
||||
|
||||
std::string BackendBuf;
|
||||
llvm::raw_string_ostream BOS(BackendBuf);
|
||||
|
||||
llvm::Mangler::getNameWithPrefix(BOS, llvm::Twine(FOS.str()), *DL);
|
||||
|
||||
return BOS.str();
|
||||
}
|
||||
|
||||
static std::string getMangledThunk(std::unique_ptr<MangleContext> &M,
|
||||
std::unique_ptr<llvm::DataLayout> &DL,
|
||||
const CXXMethodDecl *MD,
|
||||
const ThunkInfo &T) {
|
||||
std::string FrontendBuf;
|
||||
llvm::raw_string_ostream FOS(FrontendBuf);
|
||||
|
||||
M->mangleThunk(MD, T, FOS);
|
||||
|
||||
std::string BackendBuf;
|
||||
llvm::raw_string_ostream BOS(BackendBuf);
|
||||
|
||||
llvm::Mangler::getNameWithPrefix(BOS, llvm::Twine(FOS.str()), *DL);
|
||||
|
||||
return BOS.str();
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
unsigned clang_visitChildren(CXCursor parent,
|
||||
|
@ -4377,29 +4320,9 @@ CXString clang_Cursor_getMangling(CXCursor C) {
|
|||
if (!D || !(isa<FunctionDecl>(D) || isa<VarDecl>(D)))
|
||||
return cxstring::createEmpty();
|
||||
|
||||
// First apply frontend mangling.
|
||||
const NamedDecl *ND = cast<NamedDecl>(D);
|
||||
ASTContext &Ctx = ND->getASTContext();
|
||||
std::unique_ptr<MangleContext> MC(Ctx.createMangleContext());
|
||||
|
||||
std::string FrontendBuf;
|
||||
llvm::raw_string_ostream FrontendBufOS(FrontendBuf);
|
||||
if (MC->shouldMangleDeclName(ND)) {
|
||||
MC->mangleName(ND, FrontendBufOS);
|
||||
} else {
|
||||
ND->printName(FrontendBufOS);
|
||||
}
|
||||
|
||||
// Now apply backend mangling.
|
||||
std::unique_ptr<llvm::DataLayout> DL(
|
||||
new llvm::DataLayout(Ctx.getTargetInfo().getDataLayoutString()));
|
||||
|
||||
std::string FinalBuf;
|
||||
llvm::raw_string_ostream FinalBufOS(FinalBuf);
|
||||
llvm::Mangler::getNameWithPrefix(FinalBufOS, llvm::Twine(FrontendBufOS.str()),
|
||||
*DL);
|
||||
|
||||
return cxstring::createDup(FinalBufOS.str());
|
||||
ASTContext &Ctx = D->getASTContext();
|
||||
index::CodegenNameGenerator CGNameGen(Ctx);
|
||||
return cxstring::createDup(CGNameGen.getName(D));
|
||||
}
|
||||
|
||||
CXStringSet *clang_Cursor_getCXXManglings(CXCursor C) {
|
||||
|
@ -4410,49 +4333,9 @@ CXStringSet *clang_Cursor_getCXXManglings(CXCursor C) {
|
|||
if (!(isa<CXXRecordDecl>(D) || isa<CXXMethodDecl>(D)))
|
||||
return nullptr;
|
||||
|
||||
const NamedDecl *ND = cast<NamedDecl>(D);
|
||||
|
||||
ASTContext &Ctx = ND->getASTContext();
|
||||
std::unique_ptr<MangleContext> M(Ctx.createMangleContext());
|
||||
std::unique_ptr<llvm::DataLayout> DL(
|
||||
new llvm::DataLayout(Ctx.getTargetInfo().getDataLayoutString()));
|
||||
|
||||
std::vector<std::string> Manglings;
|
||||
|
||||
auto hasDefaultCXXMethodCC = [](ASTContext &C, const CXXMethodDecl *MD) {
|
||||
auto DefaultCC = C.getDefaultCallingConvention(/*IsVariadic=*/false,
|
||||
/*IsCSSMethod=*/true);
|
||||
auto CC = MD->getType()->getAs<FunctionProtoType>()->getCallConv();
|
||||
return CC == DefaultCC;
|
||||
};
|
||||
|
||||
if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(ND)) {
|
||||
Manglings.emplace_back(getMangledStructor(M, DL, CD, Ctor_Base));
|
||||
|
||||
if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily())
|
||||
if (!CD->getParent()->isAbstract())
|
||||
Manglings.emplace_back(getMangledStructor(M, DL, CD, Ctor_Complete));
|
||||
|
||||
if (Ctx.getTargetInfo().getCXXABI().isMicrosoft())
|
||||
if (CD->hasAttr<DLLExportAttr>() && CD->isDefaultConstructor())
|
||||
if (!(hasDefaultCXXMethodCC(Ctx, CD) && CD->getNumParams() == 0))
|
||||
Manglings.emplace_back(getMangledStructor(M, DL, CD,
|
||||
Ctor_DefaultClosure));
|
||||
} else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(ND)) {
|
||||
Manglings.emplace_back(getMangledStructor(M, DL, DD, Dtor_Base));
|
||||
if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily()) {
|
||||
Manglings.emplace_back(getMangledStructor(M, DL, DD, Dtor_Complete));
|
||||
if (DD->isVirtual())
|
||||
Manglings.emplace_back(getMangledStructor(M, DL, DD, Dtor_Deleting));
|
||||
}
|
||||
} else if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(ND)) {
|
||||
Manglings.emplace_back(getMangledName(M, DL, ND));
|
||||
if (MD->isVirtual())
|
||||
if (const auto *TIV = Ctx.getVTableContext()->getThunkInfo(MD))
|
||||
for (const auto &T : *TIV)
|
||||
Manglings.emplace_back(getMangledThunk(M, DL, MD, T));
|
||||
}
|
||||
|
||||
ASTContext &Ctx = D->getASTContext();
|
||||
index::CodegenNameGenerator CGNameGen(Ctx);
|
||||
std::vector<std::string> Manglings = CGNameGen.getAllManglings(D);
|
||||
return cxstring::createSet(Manglings);
|
||||
}
|
||||
|
||||
|
|
|
@ -1263,6 +1263,7 @@ static CXIdxEntityKind getEntityKindFromSymbolKind(SymbolKind K) {
|
|||
case SymbolKind::CXXTypeAlias: return CXIdxEntity_CXXTypeAlias;
|
||||
case SymbolKind::CXXInterface: return CXIdxEntity_CXXInterface;
|
||||
}
|
||||
llvm_unreachable("invalid symbol kind");
|
||||
}
|
||||
|
||||
static CXIdxEntityCXXTemplateKind
|
||||
|
@ -1275,6 +1276,7 @@ getEntityKindFromSymbolCXXTemplateKind(SymbolCXXTemplateKind K) {
|
|||
case SymbolCXXTemplateKind::TemplateSpecialization:
|
||||
return CXIdxEntity_TemplateSpecialization;
|
||||
}
|
||||
llvm_unreachable("invalid template kind");
|
||||
}
|
||||
|
||||
static CXIdxEntityLanguage getEntityLangFromSymbolLang(SymbolLanguage L) {
|
||||
|
@ -1283,4 +1285,5 @@ static CXIdxEntityLanguage getEntityLangFromSymbolLang(SymbolLanguage L) {
|
|||
case SymbolLanguage::ObjC: return CXIdxEntityLang_ObjC;
|
||||
case SymbolLanguage::CXX: return CXIdxEntityLang_CXX;
|
||||
}
|
||||
llvm_unreachable("invalid symbol language");
|
||||
}
|
||||
|
|
|
@ -1479,6 +1479,14 @@ TEST(IsInteger, ReportsNoFalsePositives) {
|
|||
to(varDecl(hasType(isInteger()))))))));
|
||||
}
|
||||
|
||||
TEST(IsAnyPointer, MatchesPointers) {
|
||||
EXPECT_TRUE(matches("int* i = nullptr;", varDecl(hasType(isAnyPointer()))));
|
||||
}
|
||||
|
||||
TEST(IsAnyPointer, ReportsNoFalsePositives) {
|
||||
EXPECT_TRUE(notMatches("int i = 0;", varDecl(hasType(isAnyPointer()))));
|
||||
}
|
||||
|
||||
TEST(IsAnyCharacter, MatchesCharacters) {
|
||||
EXPECT_TRUE(matches("char i = 0;", varDecl(hasType(isAnyCharacter()))));
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче