Merge
This commit is contained in:
commit
abbd13bc13
@ -181,26 +181,59 @@ bool ClassLoader::string_ends_with(const char* str, const char* str_to_find) {
|
||||
}
|
||||
|
||||
// Used to obtain the package name from a fully qualified class name.
|
||||
// It is the responsibility of the caller to establish ResourceMark.
|
||||
const char* ClassLoader::package_from_name(const char* class_name) {
|
||||
const char* last_slash = strrchr(class_name, '/');
|
||||
// It is the responsibility of the caller to establish a ResourceMark.
|
||||
const char* ClassLoader::package_from_name(const char* const class_name, bool* bad_class_name) {
|
||||
if (class_name == NULL) {
|
||||
if (bad_class_name != NULL) {
|
||||
*bad_class_name = true;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (bad_class_name != NULL) {
|
||||
*bad_class_name = false;
|
||||
}
|
||||
|
||||
const char* const last_slash = strrchr(class_name, '/');
|
||||
if (last_slash == NULL) {
|
||||
// No package name
|
||||
return NULL;
|
||||
}
|
||||
int length = last_slash - class_name;
|
||||
|
||||
// A class name could have just the slash character in the name,
|
||||
// resulting in a negative length.
|
||||
char* class_name_ptr = (char*) class_name;
|
||||
// Skip over '['s
|
||||
if (*class_name_ptr == '[') {
|
||||
do {
|
||||
class_name_ptr++;
|
||||
} while (*class_name_ptr == '[');
|
||||
|
||||
// Fully qualified class names should not contain a 'L'.
|
||||
// Set bad_class_name to true to indicate that the package name
|
||||
// could not be obtained due to an error condition.
|
||||
// In this situation, is_same_class_package returns false.
|
||||
if (*class_name_ptr == 'L') {
|
||||
if (bad_class_name != NULL) {
|
||||
*bad_class_name = true;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int length = last_slash - class_name_ptr;
|
||||
|
||||
// A class name could have just the slash character in the name.
|
||||
if (length <= 0) {
|
||||
// No package name
|
||||
if (bad_class_name != NULL) {
|
||||
*bad_class_name = true;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// drop name after last slash (including slash)
|
||||
// Ex., "java/lang/String.class" => "java/lang"
|
||||
char* pkg_name = NEW_RESOURCE_ARRAY(char, length + 1);
|
||||
strncpy(pkg_name, class_name, length);
|
||||
strncpy(pkg_name, class_name_ptr, length);
|
||||
*(pkg_name+length) = '\0';
|
||||
|
||||
return (const char *)pkg_name;
|
||||
@ -1117,13 +1150,11 @@ bool ClassLoader::add_package(const char *fullq_class_name, s2 classpath_index,
|
||||
assert(fullq_class_name != NULL, "just checking");
|
||||
|
||||
// Get package name from fully qualified class name.
|
||||
const char *cp = strrchr(fullq_class_name, '/');
|
||||
ResourceMark rm;
|
||||
const char *cp = package_from_name(fullq_class_name);
|
||||
if (cp != NULL) {
|
||||
int len = cp - fullq_class_name;
|
||||
PackageEntryTable* pkg_entry_tbl =
|
||||
ClassLoaderData::the_null_class_loader_data()->packages();
|
||||
TempNewSymbol pkg_symbol =
|
||||
SymbolTable::new_symbol(fullq_class_name, len, CHECK_false);
|
||||
PackageEntryTable* pkg_entry_tbl = ClassLoaderData::the_null_class_loader_data()->packages();
|
||||
TempNewSymbol pkg_symbol = SymbolTable::new_symbol(cp, CHECK_false);
|
||||
PackageEntry* pkg_entry = pkg_entry_tbl->lookup_only(pkg_symbol);
|
||||
if (pkg_entry != NULL) {
|
||||
assert(classpath_index != -1, "Unexpected classpath_index");
|
||||
@ -1231,11 +1262,9 @@ s2 ClassLoader::classloader_type(Symbol* class_name, ClassPathEntry* e, int clas
|
||||
// jimage, it is determined by the class path entry.
|
||||
jshort loader_type = ClassLoader::APP_LOADER;
|
||||
if (e->is_jrt()) {
|
||||
int length = 0;
|
||||
const jbyte* pkg_string = InstanceKlass::package_from_name(class_name, length);
|
||||
if (pkg_string != NULL) {
|
||||
ResourceMark rm;
|
||||
TempNewSymbol pkg_name = SymbolTable::new_symbol((const char*)pkg_string, length, THREAD);
|
||||
ResourceMark rm;
|
||||
TempNewSymbol pkg_name = InstanceKlass::package_from_name(class_name, CHECK_0);
|
||||
if (pkg_name != NULL) {
|
||||
const char* pkg_name_C_string = (const char*)(pkg_name->as_C_string());
|
||||
ClassPathImageEntry* cpie = (ClassPathImageEntry*)e;
|
||||
JImageFile* jimage = cpie->jimage();
|
||||
|
@ -444,7 +444,9 @@ class ClassLoader: AllStatic {
|
||||
static bool string_ends_with(const char* str, const char* str_to_find);
|
||||
|
||||
// obtain package name from a fully qualified class name
|
||||
static const char* package_from_name(const char* class_name);
|
||||
// *bad_class_name is set to true if there's a problem with parsing class_name, to
|
||||
// distinguish from a class_name with no package name, as both cases have a NULL return value
|
||||
static const char* package_from_name(const char* const class_name, bool* bad_class_name = NULL);
|
||||
|
||||
static bool is_jrt(const char* name) { return string_ends_with(name, MODULES_IMAGE_NAME); }
|
||||
|
||||
|
@ -70,6 +70,7 @@
|
||||
#include "services/threadService.hpp"
|
||||
#include "trace/traceMacros.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
#include "utilities/stringUtils.hpp"
|
||||
#include "utilities/ticks.hpp"
|
||||
#if INCLUDE_CDS
|
||||
#include "classfile/sharedClassUtil.hpp"
|
||||
@ -1154,12 +1155,10 @@ Klass* SystemDictionary::resolve_from_stream(Symbol* class_name,
|
||||
// It is illegal to define classes in the "java." package from
|
||||
// JVM_DefineClass or jni_DefineClass unless you're the bootclassloader
|
||||
ResourceMark rm(THREAD);
|
||||
char* name = parsed_name->as_C_string();
|
||||
char* index = strrchr(name, '/');
|
||||
*index = '\0'; // chop to just the package name
|
||||
while ((index = strchr(name, '/')) != NULL) {
|
||||
*index = '.'; // replace '/' with '.' in package name
|
||||
}
|
||||
TempNewSymbol pkg_name = InstanceKlass::package_from_name(parsed_name, CHECK_NULL);
|
||||
assert(pkg_name != NULL, "Error in parsing package name starting with 'java/'");
|
||||
char* name = pkg_name->as_C_string();
|
||||
StringUtils::replace_no_expand(name, "/", ".");
|
||||
const char* msg_text = "Prohibited package name: ";
|
||||
size_t len = strlen(msg_text) + strlen(name) + 1;
|
||||
char* message = NEW_RESOURCE_ARRAY(char, len);
|
||||
@ -1257,6 +1256,7 @@ instanceKlassHandle SystemDictionary::load_shared_class(
|
||||
bool SystemDictionary::is_shared_class_visible(Symbol* class_name,
|
||||
instanceKlassHandle ik,
|
||||
Handle class_loader, TRAPS) {
|
||||
ResourceMark rm;
|
||||
int path_index = ik->shared_classpath_index();
|
||||
SharedClassPathEntry* ent =
|
||||
(SharedClassPathEntry*)FileMapInfo::shared_classpath(path_index);
|
||||
@ -1270,12 +1270,11 @@ bool SystemDictionary::is_shared_class_visible(Symbol* class_name,
|
||||
TempNewSymbol pkg_name = NULL;
|
||||
PackageEntry* pkg_entry = NULL;
|
||||
ModuleEntry* mod_entry = NULL;
|
||||
int length = 0;
|
||||
const char* pkg_string = NULL;
|
||||
ClassLoaderData* loader_data = class_loader_data(class_loader);
|
||||
const jbyte* pkg_string = InstanceKlass::package_from_name(class_name, length);
|
||||
if (pkg_string != NULL) {
|
||||
pkg_name = SymbolTable::new_symbol((const char*)pkg_string,
|
||||
length, CHECK_(false));
|
||||
pkg_name = InstanceKlass::package_from_name(class_name, CHECK_false);
|
||||
if (pkg_name != NULL) {
|
||||
pkg_string = pkg_name->as_C_string();
|
||||
if (loader_data != NULL) {
|
||||
pkg_entry = loader_data->packages()->lookup_only(pkg_name);
|
||||
}
|
||||
@ -1432,15 +1431,14 @@ instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Ha
|
||||
instanceKlassHandle nh = instanceKlassHandle(); // null Handle
|
||||
|
||||
if (class_loader.is_null()) {
|
||||
int length = 0;
|
||||
ResourceMark rm;
|
||||
PackageEntry* pkg_entry = NULL;
|
||||
bool search_only_bootloader_append = false;
|
||||
ClassLoaderData *loader_data = class_loader_data(class_loader);
|
||||
|
||||
// Find the package in the boot loader's package entry table.
|
||||
const jbyte* pkg_string = InstanceKlass::package_from_name(class_name, length);
|
||||
if (pkg_string != NULL) {
|
||||
TempNewSymbol pkg_name = SymbolTable::new_symbol((const char*)pkg_string, length, CHECK_(nh));
|
||||
TempNewSymbol pkg_name = InstanceKlass::package_from_name(class_name, CHECK_NULL);
|
||||
if (pkg_name != NULL) {
|
||||
pkg_entry = loader_data->packages()->lookup_only(pkg_name);
|
||||
}
|
||||
|
||||
@ -1477,7 +1475,7 @@ instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Ha
|
||||
assert(!DumpSharedSpaces, "Archive dumped after module system initialization");
|
||||
// After the module system has been initialized, check if the class'
|
||||
// package is in a module defined to the boot loader.
|
||||
if (pkg_string == NULL || pkg_entry == NULL || pkg_entry->in_unnamed_module()) {
|
||||
if (pkg_name == NULL || pkg_entry == NULL || pkg_entry->in_unnamed_module()) {
|
||||
// Class is either in the unnamed package, in a named package
|
||||
// within a module not defined to the boot loader or in a
|
||||
// a named package within the unnamed module. In all cases,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -48,7 +48,7 @@ public:
|
||||
static bool is_shared_class_visible_for_classloader(
|
||||
instanceKlassHandle ik,
|
||||
Handle class_loader,
|
||||
const jbyte* pkg_string,
|
||||
const char* pkg_string,
|
||||
Symbol* pkg_name,
|
||||
PackageEntry* pkg_entry,
|
||||
ModuleEntry* mod_entry,
|
||||
|
@ -2182,39 +2182,21 @@ const char* InstanceKlass::signature_name() const {
|
||||
return dest;
|
||||
}
|
||||
|
||||
const jbyte* InstanceKlass::package_from_name(const Symbol* name, int& length) {
|
||||
ResourceMark rm;
|
||||
length = 0;
|
||||
// Used to obtain the package name from a fully qualified class name.
|
||||
Symbol* InstanceKlass::package_from_name(const Symbol* name, TRAPS) {
|
||||
if (name == NULL) {
|
||||
return NULL;
|
||||
} else {
|
||||
const jbyte* base_name = name->base();
|
||||
const jbyte* last_slash = UTF8::strrchr(base_name, name->utf8_length(), '/');
|
||||
|
||||
if (last_slash == NULL) {
|
||||
// No package name
|
||||
if (name->utf8_length() <= 0) {
|
||||
return NULL;
|
||||
} else {
|
||||
// Skip over '['s
|
||||
if (*base_name == '[') {
|
||||
do {
|
||||
base_name++;
|
||||
} while (*base_name == '[');
|
||||
if (*base_name != 'L') {
|
||||
// Fully qualified class names should not contain a 'L'.
|
||||
// Set length to -1 to indicate that the package name
|
||||
// could not be obtained due to an error condition.
|
||||
// In this situtation, is_same_class_package returns false.
|
||||
length = -1;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Found the package name, look it up in the symbol table.
|
||||
length = last_slash - base_name;
|
||||
assert(length > 0, "Bad length for package name");
|
||||
return base_name;
|
||||
}
|
||||
ResourceMark rm;
|
||||
const char* package_name = ClassLoader::package_from_name((const char*) name->as_C_string());
|
||||
if (package_name == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
Symbol* pkg_name = SymbolTable::new_symbol(package_name, THREAD);
|
||||
return pkg_name;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2230,12 +2212,9 @@ ModuleEntry* InstanceKlass::module() const {
|
||||
}
|
||||
|
||||
void InstanceKlass::set_package(ClassLoaderData* loader_data, TRAPS) {
|
||||
int length = 0;
|
||||
const jbyte* base_name = package_from_name(name(), length);
|
||||
|
||||
if (base_name != NULL && loader_data != NULL) {
|
||||
TempNewSymbol pkg_name = SymbolTable::new_symbol((const char*)base_name, length, CHECK);
|
||||
TempNewSymbol pkg_name = package_from_name(name(), CHECK);
|
||||
|
||||
if (pkg_name != NULL && loader_data != NULL) {
|
||||
// Find in class loader's package entry table.
|
||||
_package_entry = loader_data->packages()->lookup_only(pkg_name);
|
||||
|
||||
@ -2331,20 +2310,18 @@ bool InstanceKlass::is_same_class_package(oop class_loader1, const Symbol* class
|
||||
if (class_loader1 != class_loader2) {
|
||||
return false;
|
||||
} else if (class_name1 == class_name2) {
|
||||
return true; // skip painful bytewise comparison
|
||||
return true;
|
||||
} else {
|
||||
ResourceMark rm;
|
||||
|
||||
// The Symbol*'s are in UTF8 encoding. Since we only need to check explicitly
|
||||
// for ASCII characters ('/', 'L', '['), we can keep them in UTF8 encoding.
|
||||
// Otherwise, we just compare jbyte values between the strings.
|
||||
int length1 = 0;
|
||||
int length2 = 0;
|
||||
const jbyte *name1 = package_from_name(class_name1, length1);
|
||||
const jbyte *name2 = package_from_name(class_name2, length2);
|
||||
bool bad_class_name = false;
|
||||
const char* name1 = ClassLoader::package_from_name((const char*) class_name1->as_C_string(), &bad_class_name);
|
||||
if (bad_class_name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((length1 < 0) || (length2 < 0)) {
|
||||
// error occurred parsing package name.
|
||||
const char* name2 = ClassLoader::package_from_name((const char*) class_name2->as_C_string(), &bad_class_name);
|
||||
if (bad_class_name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2354,13 +2331,13 @@ bool InstanceKlass::is_same_class_package(oop class_loader1, const Symbol* class
|
||||
return name1 == name2;
|
||||
}
|
||||
|
||||
// Check that package part is identical
|
||||
return UTF8::equal(name1, length1, name2, length2);
|
||||
// Check that package is identical
|
||||
return (strcmp(name1, name2) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true iff super_method can be overridden by a method in targetclassname
|
||||
// See JSL 3rd edition 8.4.6.1
|
||||
// See JLS 3rd edition 8.4.6.1
|
||||
// Assumes name-signature match
|
||||
// "this" is InstanceKlass of super_method which must exist
|
||||
// note that the InstanceKlass of the method in the targetclassname has not always been created yet
|
||||
|
@ -1108,7 +1108,7 @@ public:
|
||||
|
||||
// Naming
|
||||
const char* signature_name() const;
|
||||
static const jbyte* package_from_name(const Symbol* name, int& length);
|
||||
static Symbol* package_from_name(const Symbol* name, TRAPS);
|
||||
|
||||
// GC specific object visitors
|
||||
//
|
||||
|
@ -246,7 +246,7 @@ class Method : public Metadata {
|
||||
int code_size() const { return constMethod()->code_size(); }
|
||||
|
||||
// method size in words
|
||||
int method_size() const { return sizeof(Method)/wordSize + is_native() ? 2 : 0; }
|
||||
int method_size() const { return sizeof(Method)/wordSize + ( is_native() ? 2 : 0 ); }
|
||||
|
||||
// constant pool for Klass* holding this method
|
||||
ConstantPool* constants() const { return constMethod()->constants(); }
|
||||
|
92
hotspot/test/native/runtime/test_classLoader.cpp
Normal file
92
hotspot/test/native/runtime/test_classLoader.cpp
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "classfile/classLoader.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "unittest.hpp"
|
||||
|
||||
// Tests ClassLoader::package_from_name()
|
||||
TEST_VM(classLoader, null_class_name) {
|
||||
ResourceMark rm;
|
||||
bool bad_class_name = false;
|
||||
const char* retval= ClassLoader::package_from_name(NULL, &bad_class_name);
|
||||
ASSERT_TRUE(bad_class_name) << "Function did not set bad_class_name with NULL class name";
|
||||
ASSERT_STREQ(retval, NULL) << "Wrong package for NULL class name pointer";
|
||||
}
|
||||
|
||||
TEST_VM(classLoader, empty_class_name) {
|
||||
ResourceMark rm;
|
||||
const char* retval = ClassLoader::package_from_name("");
|
||||
ASSERT_STREQ(retval, NULL) << "Wrong package for empty string";
|
||||
}
|
||||
|
||||
TEST_VM(classLoader, no_slash) {
|
||||
ResourceMark rm;
|
||||
const char* retval = ClassLoader::package_from_name("L");
|
||||
ASSERT_STREQ(retval, NULL) << "Wrong package for class with no slashes";
|
||||
}
|
||||
|
||||
TEST_VM(classLoader, just_slash) {
|
||||
ResourceMark rm;
|
||||
bool bad_class_name = false;
|
||||
const char* retval = ClassLoader::package_from_name("/", &bad_class_name);
|
||||
ASSERT_TRUE(bad_class_name) << "Function did not set bad_class_name with package of length 0";
|
||||
ASSERT_STREQ(retval, NULL) << "Wrong package for class with just slash";
|
||||
}
|
||||
|
||||
TEST_VM(classLoader, multiple_slashes) {
|
||||
ResourceMark rm;
|
||||
const char* retval = ClassLoader::package_from_name("///");
|
||||
ASSERT_STREQ(retval, "//") << "Wrong package for class with just slashes";
|
||||
}
|
||||
|
||||
TEST_VM(classLoader, standard_case_1) {
|
||||
ResourceMark rm;
|
||||
bool bad_class_name = true;
|
||||
const char* retval = ClassLoader::package_from_name("package/class", &bad_class_name);
|
||||
ASSERT_FALSE(bad_class_name) << "Function did not reset bad_class_name";
|
||||
ASSERT_STREQ(retval, "package") << "Wrong package for class with one slash";
|
||||
}
|
||||
|
||||
TEST_VM(classLoader, standard_case_2) {
|
||||
ResourceMark rm;
|
||||
const char* retval = ClassLoader::package_from_name("package/folder/class");
|
||||
ASSERT_STREQ(retval, "package/folder") << "Wrong package for class with multiple slashes";
|
||||
}
|
||||
|
||||
TEST_VM(classLoader, class_array) {
|
||||
ResourceMark rm;
|
||||
bool bad_class_name = false;
|
||||
const char* retval = ClassLoader::package_from_name("[package/class", &bad_class_name);
|
||||
ASSERT_FALSE(bad_class_name) << "Function set bad_class_name with class array";
|
||||
ASSERT_STREQ(retval, "package") << "Wrong package for class with leading bracket";
|
||||
}
|
||||
|
||||
TEST_VM(classLoader, class_object_array) {
|
||||
ResourceMark rm;
|
||||
bool bad_class_name = false;
|
||||
const char* retval = ClassLoader::package_from_name("[Lpackage/class", &bad_class_name);
|
||||
ASSERT_TRUE(bad_class_name) << "Function did not set bad_class_name with array of class objects";
|
||||
ASSERT_STREQ(retval, NULL) << "Wrong package for class with leading '[L'";
|
||||
}
|
35
hotspot/test/native/runtime/test_instanceKlass.cpp
Normal file
35
hotspot/test/native/runtime/test_instanceKlass.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "classfile/symbolTable.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "oops/instanceKlass.hpp"
|
||||
#include "unittest.hpp"
|
||||
|
||||
// Tests InstanceKlass::package_from_name()
|
||||
TEST_VM(instanceKlass, null_symbol) {
|
||||
ResourceMark rm;
|
||||
TempNewSymbol package_sym = InstanceKlass::package_from_name(NULL, NULL);
|
||||
ASSERT_TRUE(package_sym == NULL) << "Wrong package for NULL symbol";
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user