Browse Source

Replace the existing VS lookup code with the one from Clang driver (it works better).

pull/1/head
triton 12 years ago
parent
commit
27d7b19e7f
  1. 82
      src/Parser/Parser.cpp
  2. 317
      src/Parser/VSLookup.cpp

82
src/Parser/Parser.cpp

@ -63,9 +63,7 @@ static std::string GetClangBuiltinIncludeDir() @@ -63,9 +63,7 @@ static std::string GetClangBuiltinIncludeDir()
//-----------------------------------//
#ifdef _MSC_VER
bool GetVisualStudioEnv(const char* env,
std::vector<std::string>& pathes,
int probeFrom = 0, int probeTo = 0);
std::vector<std::string> GetWindowsSystemIncludeDirs();
#endif
void Parser::Setup(ParserOptions^ Opts)
@ -122,28 +120,14 @@ void Parser::Setup(ParserOptions^ Opts) @@ -122,28 +120,14 @@ void Parser::Setup(ParserOptions^ Opts)
C->getHeaderSearchOpts().AddPath(GetClangBuiltinIncludeDir(),
clang::frontend::System, false, false);
#if defined(WithClangWindowsSystemIncludeDirsPatch)
std::vector<std::string> SystemDirs = clang::driver::GetWindowsSystemIncludeDirs();
clang::HeaderSearchOptions& HSOpts = C->getHeaderSearchOpts();
for(size_t i = 0; i < SystemDirs.size(); ++i)
{
HSOpts.AddPath(SystemDirs[i], frontend::System, false, false, true);
}
#endif
#ifdef _MSC_VER
std::vector<std::string> SystemDirs;
if(GetVisualStudioEnv("INCLUDE", SystemDirs, Opts->ToolSetToUse, Opts->ToolSetToUse))
{
std::vector<std::string> SystemDirs = clang::driver::GetWindowsSystemIncludeDirs();
clang::HeaderSearchOptions& HSOpts = C->getHeaderSearchOpts();
for(size_t i = 0; i < SystemDirs.size(); ++i)
{
HSOpts.AddPath(SystemDirs[i], frontend::System, false, false);
}
}
#endif
C->createPreprocessor();
@ -323,6 +307,12 @@ Cxxi::Class^ Parser::WalkRecordCXX(clang::CXXRecordDecl* Record, bool IsDependen @@ -323,6 +307,12 @@ Cxxi::Class^ Parser::WalkRecordCXX(clang::CXXRecordDecl* Record, bool IsDependen
using namespace clang;
using namespace clix;
//if (Record->isAnonymousStructOrUnion())
//{
// //assert(0);
// return nullptr;
//}
if (Record->hasFlexibleArrayMember())
{
assert(0);
@ -600,6 +590,12 @@ Cxxi::Namespace^ Parser::GetNamespace(const clang::NamedDecl* ND) @@ -600,6 +590,12 @@ Cxxi::Namespace^ Parser::GetNamespace(const clang::NamedDecl* ND)
// We might be able to translate these to C# nested types.
continue;
}
case Decl::ClassTemplateSpecialization:
{
// FIXME: Ignore ClassTemplateSpecialization namespaces...
// We might be able to translate these to C# nested types.
continue;
}
default:
{
StringRef Kind = Ctx->getDeclKindName();
@ -656,6 +652,37 @@ static Cxxi::PrimitiveType WalkBuiltinType(const clang::BuiltinType* Builtin) @@ -656,6 +652,37 @@ static Cxxi::PrimitiveType WalkBuiltinType(const clang::BuiltinType* Builtin)
//-----------------------------------//
clang::TypeLoc ResolveTypeLoc(clang::TypeLoc TL, clang::TypeLoc::TypeLocClass Class)
{
using namespace clang;
auto TypeLocClass = TL.getTypeLocClass();
if (TypeLocClass == Class)
{
return TL;
}
if (TypeLocClass == TypeLoc::Qualified)
{
auto UTL = TL.getUnqualifiedLoc();
TL = UTL;
}
else if (TypeLocClass == TypeLoc::Elaborated)
{
auto ETL = TL.getAs<ElaboratedTypeLoc>();
auto ITL = ETL.getNextTypeLoc();
TL = ITL;
}
else if (TypeLocClass == TypeLoc::Paren)
{
auto PTL = TL.getAs<ParenTypeLoc>();
TL = PTL.getNextTypeLoc();
}
assert(TL.getTypeLocClass() == Class);
return TL;
}
Cxxi::Type^ Parser::WalkType(clang::QualType QualType, clang::TypeLoc* TL,
bool DesugarType)
{
@ -884,11 +911,19 @@ Cxxi::Type^ Parser::WalkType(clang::QualType QualType, clang::TypeLoc* TL, @@ -884,11 +911,19 @@ Cxxi::Type^ Parser::WalkType(clang::QualType QualType, clang::TypeLoc* TL,
case Type::TemplateTypeParm:
{
auto TP = Type->getAs<TemplateTypeParmType>();
auto TPT = gcnew Cxxi::TemplateParameterType();
//TPT->Parameter = WalkDeclaration(TP->getDecl());
if (auto Ident = TP->getIdentifier())
TPT->Parameter.Name = marshalString<E_UTF8>(Ident->getName());
return TPT;
}
case Type::SubstTemplateTypeParm:
{
auto TPT = gcnew Cxxi::TemplateParameterType();
return TPT;
}
case Type::InjectedClassName:
{
auto MYIN = Type->getAs<InjectedClassNameType>();
@ -1053,6 +1088,7 @@ void Parser::WalkFunction(clang::FunctionDecl* FD, Cxxi::Function^ F, @@ -1053,6 +1088,7 @@ void Parser::WalkFunction(clang::FunctionDecl* FD, Cxxi::Function^ F,
if (auto TSI = FD->getTypeSourceInfo())
{
TypeLoc TL = TSI->getTypeLoc();
//RTL = ResolveTypeLoc(TL).getAs<FunctionTypeLoc>.getResultLoc();
RTL = TL.getAs<FunctionTypeLoc>().getResultLoc();
}
F->ReturnType = WalkType(FD->getResultType(), &RTL);
@ -1498,6 +1534,14 @@ Cxxi::Declaration^ Parser::WalkDeclaration(clang::Decl* D, clang::TypeLoc* TL, @@ -1498,6 +1534,14 @@ Cxxi::Declaration^ Parser::WalkDeclaration(clang::Decl* D, clang::TypeLoc* TL,
default:
{
Debug("Unhandled declaration kind: %s\n", D->getDeclKindName());
auto &SM = C->getSourceManager();
auto Loc = D->getLocation();
auto FileName = SM.getFilename(Loc);
auto Offset = SM.getFileOffset(Loc);
auto LineNo = SM.getLineNumber(SM.getFileID(Loc), Offset);
Debug(" %s (line %u)\n", FileName, LineNo);
break;
} };

317
src/Parser/VSLookup.cpp

@ -9,102 +9,275 @@ @@ -9,102 +9,275 @@
#include <string>
#include <vector>
#include <cstdio>
static std::string exec(const char* cmd)
{
FILE* pipe = _popen(cmd, "r");
if (!pipe) return "ERROR";
char buffer[128];
std::string result = "";
while(!feof(pipe)) {
if(fgets(buffer, 128, pipe) != NULL)
result += buffer;
}
_pclose(pipe);
return result;
}
#pragma comment(lib, "shlwapi.lib") //_popen, _pclose
#include <shlwapi.h>
//
// Returns true if got settings, false if not.
//
bool GetVisualStudioEnv(
const char* envVar, // [in] "INCLUDE" / "LIBPATH"
std::vector<std::string>& vecPathes,
int iProbeFrom = 0, int iProbeTo = 0 // 2005 - 8, 2008 - 9, 2010 - 10
)
{
std::string s;
if( iProbeFrom == 0 && iProbeTo == 0 )
{
// Environment variable specifies which VS to use.
if( getenv("VSENV") != NULL )
{
int iVer = atoi( getenv("VSENV") );
if( iVer == 0 )
return false;
return GetVisualStudioEnv(envVar, vecPathes, iVer, iVer );
// Include the necessary headers to interface with the Windows registry and
// environment.
#define WIN32_LEAN_AND_MEAN
#define NOGDI
#define NOMINMAX
#include <Windows.h>
// Has all the registry lookup related code
struct MSVCRegLookup {
HKEY hRootKey;
HKEY hKey;
const char* subKey;
DWORD valueType;
MSVCRegLookup()
: hRootKey(NULL), hKey(NULL), subKey(NULL), valueType(0) { }
bool InitializeRootKey(const char *keyPath) {
if (strncmp(keyPath, "HKEY_CLASSES_ROOT\\", 18) == 0) {
hRootKey = HKEY_CLASSES_ROOT;
subKey = keyPath + 18;
} else if (strncmp(keyPath, "HKEY_USERS\\", 11) == 0) {
hRootKey = HKEY_USERS;
subKey = keyPath + 11;
} else if (strncmp(keyPath, "HKEY_LOCAL_MACHINE\\", 19) == 0) {
hRootKey = HKEY_LOCAL_MACHINE;
subKey = keyPath + 19;
} else if (strncmp(keyPath, "HKEY_CURRENT_USER\\", 18) == 0) {
hRootKey = HKEY_CURRENT_USER;
subKey = keyPath + 18;
} else {
return false;
}
return true;
}
iProbeFrom = 20;
iProbeTo = 9;
bool FindSimpleKeyValue(const char *valueName, char *value, DWORD valueSize) {
bool Ret = false;
long Res = RegOpenKeyExA(hRootKey, subKey, 0, KEY_READ, &hKey);
if (Res == ERROR_SUCCESS) {
Res = RegQueryValueExA(hKey, valueName, NULL, &valueType,
(LPBYTE)value, &valueSize);
if (Res == ERROR_SUCCESS)
Ret = true;
RegCloseKey(hKey);
}
return Ret;
}
for( int iProbeVer = iProbeFrom; iProbeVer >= iProbeTo; iProbeVer-- )
{
char envvar[64];
sprintf(envvar, "VS%d0COMNTOOLS", iProbeVer);
bool FindBestVersionKeyValue(const char* versionIndex,
const char *valueName, char *value, DWORD valueSize) {
bool Ret = false;
const char *keyEnd = versionIndex - 1;
const char *nextKey = versionIndex;
// Not defined
if( getenv(envvar) == NULL )
continue;
// Find end of previous key.
while ((keyEnd > subKey) && (*keyEnd != '\\'))
keyEnd--;
// Find end of key containing $VERSION.
while (*nextKey && (*nextKey != '\\'))
nextKey++;
size_t partialKeyLength = keyEnd - subKey;
char partialKey[256];
if (partialKeyLength > sizeof(partialKey))
partialKeyLength = sizeof(partialKey);
strncpy(partialKey, subKey, partialKeyLength);
partialKey[partialKeyLength] = '\0';
std::string cmd = getenv(envvar);
cmd += "\\..\\..\\vc\\vcvarsall.bat";
HKEY hTopKey = NULL;
long Res = RegOpenKeyExA(hRootKey, partialKey, 0, KEY_READ, &hTopKey);
if( !PathFileExistsA( cmd.c_str() ) )
if (Res != ERROR_SUCCESS)
return false;
char keyName[256];
int bestIndex = -1;
char bestName[256];
bestName[0] = '\0';
double bestValue = 0.0;
// Find the highest versioned key.
DWORD index, size = sizeof(keyName) - 1;
for (index = 0; RegEnumKeyExA(hTopKey, index, keyName, &size, NULL,
NULL, NULL, NULL) == ERROR_SUCCESS; index++) {
const char *sp = keyName;
while (*sp && !isdigit(*sp))
sp++;
if (!*sp)
continue;
const char *ep = sp + 1;
while (*ep && (isdigit(*ep) || (*ep == '.')))
ep++;
char numBuf[32];
strncpy(numBuf, sp, sizeof(numBuf) - 1);
numBuf[sizeof(numBuf) - 1] = '\0';
//printf("Located: %s", envvar);
double versionValue = strtod(numBuf, NULL);
if (versionValue > bestValue) {
// Better values are only better if the desired key exists for them.
std::string candidate = std::string(keyName) + nextKey;
Res = RegOpenKeyExA(hTopKey, candidate.c_str(), 0, KEY_READ, &hKey);
if (Res == ERROR_SUCCESS) {
Res = RegQueryValueExA(hKey, valueName, NULL, &valueType,
(LPBYTE)value, &valueSize);
if (Res == ERROR_SUCCESS) {
bestIndex = (int)index;
bestValue = versionValue;
strcpy(bestName, keyName);
}
RegCloseKey(hKey);
}
}
}
cmd = "cmd /C \"" + cmd + "\" ^>nul ^& set";
s = exec(cmd.c_str());
break;
// If we found the highest versioned key, open the key and get the value.
if (bestIndex != -1) {
// Append rest of key.
strncat(bestName, nextKey, sizeof(bestName) - 1);
bestName[sizeof(bestName) - 1] = '\0';
// Open the chosen key path remainder.
Res = RegOpenKeyExA(hTopKey, bestName, 0, KEY_READ, &hKey);
if (Res == ERROR_SUCCESS) {
Res = RegQueryValueExA(hKey, valueName, NULL, &valueType,
(LPBYTE)value, &valueSize);
if (Res == ERROR_SUCCESS)
Ret = true;
RegCloseKey(hKey);
}
}
RegCloseKey(hTopKey);
return Ret;
}
};
if( s.length() == 0 )
/// \brief Read registry string.
/// This also supports a means to look for high-versioned keys by use
/// of a $VERSION placeholder in the key path.
/// $VERSION in the key path is a placeholder for the version number,
/// causing the highest value path to be searched for and used.
/// I.e. "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION".
/// There can be additional characters in the component. Only the numeric
/// characters are compared.
static bool getSystemRegistryString(const char *keyPath, const char *valueName,
char *value, size_t maxLength) {
MSVCRegLookup Reg;
if (!Reg.InitializeRootKey(keyPath))
return false;
char* envline;
const char* versionIndex = strstr(Reg.subKey, "$VERSION");
// If we have a $VERSION placeholder, do the highest-version search.
if (versionIndex)
return Reg.FindBestVersionKeyValue(versionIndex, valueName,
value, maxLength-1);
else
return Reg.FindSimpleKeyValue(valueName, value, maxLength-1);
}
vecPathes.clear();
/// \brief Get Windows SDK installation directory.
static bool getWindowsSDKDir(std::string &path) {
char windowsSDKInstallDir[256];
// Try the Windows registry.
bool hasSDKDir = getSystemRegistryString(
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
"InstallationFolder",
windowsSDKInstallDir,
sizeof(windowsSDKInstallDir) - 1);
// If we have both vc80 and vc90, pick version we were compiled with.
if (hasSDKDir && windowsSDKInstallDir[0]) {
path = windowsSDKInstallDir;
return true;
}
return false;
}
for (envline = strtok( &s[0], "\n" ); envline; envline = strtok( NULL, "\n" ))
{
char* varend = strchr( envline, '=');
if( !varend )
continue;
// Get Visual Studio installation directory.
static bool getVisualStudioDir(std::string &path) {
// First check the environment variables that vsvars32.bat sets.
const char* vcinstalldir = getenv("VCINSTALLDIR");
if (vcinstalldir) {
char *p = const_cast<char *>(strstr(vcinstalldir, "\\VC"));
if (p)
*p = '\0';
path = vcinstalldir;
return true;
}
*varend = 0;
char vsIDEInstallDir[256];
char vsExpressIDEInstallDir[256];
// Then try the windows registry.
bool hasVCDir = getSystemRegistryString(
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION",
"InstallDir", vsIDEInstallDir, sizeof(vsIDEInstallDir) - 1);
bool hasVCExpressDir = getSystemRegistryString(
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\$VERSION",
"InstallDir", vsExpressIDEInstallDir, sizeof(vsExpressIDEInstallDir) - 1);
// If we have both vc80 and vc90, pick version we were compiled with.
if (hasVCDir && vsIDEInstallDir[0]) {
char *p = (char*)strstr(vsIDEInstallDir, "\\Common7\\IDE");
if (p)
*p = '\0';
path = vsIDEInstallDir;
return true;
}
if( strcmp(envline,envVar) == 0 )
{
char* val;
for (val = strtok( varend + 1, ";" ); val; val = strtok( NULL, ";" ))
{
vecPathes.push_back(val);
if (hasVCExpressDir && vsExpressIDEInstallDir[0]) {
char *p = (char*)strstr(vsExpressIDEInstallDir, "\\Common7\\IDE");
if (p)
*p = '\0';
path = vsExpressIDEInstallDir;
return true;
}
// Try the environment.
const char *vs100comntools = getenv("VS100COMNTOOLS");
const char *vs90comntools = getenv("VS90COMNTOOLS");
const char *vs80comntools = getenv("VS80COMNTOOLS");
const char *vscomntools = NULL;
// Try to find the version that we were compiled with
if(false) {}
#if (_MSC_VER >= 1600) // VC100
else if(vs100comntools) {
vscomntools = vs100comntools;
}
*varend = '=';
#elif (_MSC_VER == 1500) // VC80
else if(vs90comntools) {
vscomntools = vs90comntools;
}
#elif (_MSC_VER == 1400) // VC80
else if(vs80comntools) {
vscomntools = vs80comntools;
}
#endif
// Otherwise find any version we can
else if (vs100comntools)
vscomntools = vs100comntools;
else if (vs90comntools)
vscomntools = vs90comntools;
else if (vs80comntools)
vscomntools = vs80comntools;
if (vscomntools && *vscomntools) {
const char *p = strstr(vscomntools, "\\Common7\\Tools");
path = p ? std::string(vscomntools, p) : vscomntools;
return true;
}
return false;
}
std::vector<std::string> GetWindowsSystemIncludeDirs() {
std::vector<std::string> Paths;
std::string VSDir;
std::string WindowsSDKDir;
// When built with access to the proper Windows APIs, try to actually find
// the correct include paths first.
if (getVisualStudioDir(VSDir)) {
Paths.push_back(VSDir + "\\VC\\include");
if (getWindowsSDKDir(WindowsSDKDir))
Paths.push_back(WindowsSDKDir + "\\include");
else
Paths.push_back(VSDir + "\\VC\\PlatformSDK\\Include");
}
return Paths;
}
#endif
Loading…
Cancel
Save